diff --git a/test/integration/menu-bar-tooltip.test.js b/test/integration/menu-bar-tooltip.test.js
index 86ead0c7e0..d8a6c937ff 100644
--- a/test/integration/menu-bar-tooltip.test.js
+++ b/test/integration/menu-bar-tooltip.test.js
@@ -7,12 +7,15 @@ import {
fixtureSync,
focusin,
focusout,
+ middleOfNode,
mousedown,
nextRender,
tabKeyDown,
} from '@vaadin/testing-helpers';
+import { resetMouse, sendKeys, sendMouse } from '@web/test-runner-commands';
import sinon from 'sinon';
import '@vaadin/menu-bar';
+import './not-animated-styles.js';
import { Tooltip } from '@vaadin/tooltip';
import { mouseenter, mouseleave } from '@vaadin/tooltip/test/helpers.js';
@@ -34,316 +37,393 @@ describe('menu-bar with tooltip', () => {
Tooltip.setDefaultHideDelay(0);
});
- beforeEach(async () => {
- menuBar = fixtureSync(`
-
-
-
- `);
- menuBar.items = [
- { text: 'Edit', tooltip: 'Edit tooltip' },
- {
- text: 'Share',
- children: [{ text: 'By email' }],
- },
- {
- text: 'Move',
- tooltip: 'Move tooltip',
- children: [{ text: 'To folder' }],
- },
- ];
-
- await nextRender();
- buttons = menuBar._buttons;
-
- tooltip = menuBar.querySelector('vaadin-tooltip');
- });
-
- it('should set manual on the tooltip to true', () => {
- expect(tooltip.manual).to.be.true;
- });
-
- it('should show tooltip on menu button mouseover', () => {
- mouseover(buttons[0]);
- expect(tooltip.opened).to.be.true;
- });
-
- it('should use the tooltip property of an item as tooltip', () => {
- mouseover(buttons[0]);
- expect(getTooltipText()).to.equal('Edit tooltip');
- });
-
- it('should not show tooltip for an item which has no tooltip', () => {
- mouseover(buttons[1]);
- expect(getTooltipText()).not.to.be.ok;
- });
-
- it('should not show tooltip on another parent menu button mouseover when open', async () => {
- mouseover(buttons[1]);
- buttons[1].click();
- await nextRender();
- mouseover(buttons[2]);
- await nextRender();
- expect(tooltip.opened).to.be.false;
- });
-
- it('should hide tooltip on menu bar mouseleave', () => {
- mouseover(buttons[0]);
- mouseleave(menuBar);
- expect(tooltip.opened).to.be.false;
- });
-
- it('should hide tooltip on menu bar container mouseover', () => {
- mouseover(buttons[0]);
- mouseover(menuBar._container);
- expect(tooltip.opened).to.be.false;
- });
-
- it('should show tooltip again on menu bar button mouseover', () => {
- mouseover(buttons[0]);
- mouseover(menuBar._container);
- mouseover(buttons[1]);
- expect(tooltip.opened).to.be.true;
- });
-
- it('should set tooltip target on menu button mouseover', () => {
- mouseover(buttons[0]);
- expect(tooltip.target).to.be.equal(buttons[0]);
- });
-
- it('should set tooltip context on menu button mouseover', () => {
- mouseover(buttons[0]);
- expect(tooltip.context).to.be.instanceOf(Object);
- expect(tooltip.context.item.text).to.equal('Edit');
- });
-
- it('should change tooltip context on another menu button mouseover', () => {
- mouseover(buttons[0]);
- mouseover(buttons[1]);
- expect(tooltip.context.item.text).to.equal('Share');
- });
-
- it('should hide tooltip on menu button mousedown', () => {
- mouseover(buttons[0]);
- mousedown(buttons[0]);
- expect(tooltip.opened).to.be.false;
- });
-
- it('should hide tooltip on mouseleave from overlay to outside', () => {
- const overlay = tooltip._overlayElement;
- mouseover(buttons[0]);
- mouseenter(overlay);
- mouseleave(overlay);
- expect(overlay.opened).to.be.false;
- });
-
- it('should not show tooltip on focus without keyboard interaction', async () => {
- buttons[0].focus();
- await nextRender();
- expect(tooltip.opened).to.be.false;
- });
-
- it('should show tooltip on menu button keyboard focus', () => {
- tabKeyDown(document.body);
- focusin(buttons[0]);
- expect(tooltip.opened).to.be.true;
- });
-
- it('should not show tooltip on another parent menu button focus when open', async () => {
- buttons[0].focus();
- arrowRight(buttons[0]);
- arrowDown(buttons[1]);
- arrowRight(buttons[1]);
- await nextRender();
- expect(tooltip.opened).to.be.false;
- });
+ describe('default', () => {
+ beforeEach(async () => {
+ menuBar = fixtureSync(`
+
+
+
+ `);
+ menuBar.items = [
+ { text: 'Edit', tooltip: 'Edit tooltip' },
+ {
+ text: 'Share',
+ children: [{ text: 'By email' }],
+ },
+ {
+ text: 'Move',
+ tooltip: 'Move tooltip',
+ children: [{ text: 'To folder' }],
+ },
+ ];
- it('should set tooltip target on menu button keyboard focus', () => {
- tabKeyDown(document.body);
- focusin(buttons[0]);
- expect(tooltip.target).to.be.equal(buttons[0]);
- });
+ await nextRender();
+ buttons = menuBar._buttons;
- it('should set tooltip context on menu button keyboard focus', () => {
- tabKeyDown(document.body);
- focusin(buttons[0]);
- expect(tooltip.context).to.be.instanceOf(Object);
- expect(tooltip.context.item.text).to.equal('Edit');
- });
+ tooltip = menuBar.querySelector('vaadin-tooltip');
+ });
- it('should hide tooltip on menu-bar focusout', () => {
- tabKeyDown(document.body);
- focusin(buttons[0]);
- focusout(menuBar);
- expect(tooltip.opened).to.be.false;
- });
+ it('should set manual on the tooltip to true', () => {
+ expect(tooltip.manual).to.be.true;
+ });
- it('should hide tooltip on menuBar menu button content Esc', () => {
- tabKeyDown(document.body);
- focusin(buttons[0]);
- escKeyDown(buttons[0]);
- expect(tooltip.opened).to.be.false;
- });
+ it('should show tooltip on menu button mouseover', () => {
+ mouseover(buttons[0]);
+ expect(tooltip.opened).to.be.true;
+ });
- it('should set tooltip opened to false when the menuBar is removed', () => {
- mouseover(buttons[0]);
+ it('should use the tooltip property of an item as tooltip', () => {
+ mouseover(buttons[0]);
+ expect(getTooltipText()).to.equal('Edit tooltip');
+ });
- menuBar.remove();
+ it('should not show tooltip for an item which has no tooltip', () => {
+ mouseover(buttons[1]);
+ expect(getTooltipText()).not.to.be.ok;
+ });
- expect(tooltip.opened).to.be.false;
- });
+ it('should not show tooltip on another parent menu button mouseover when open', async () => {
+ mouseover(buttons[1]);
+ buttons[1].click();
+ await nextRender();
+ mouseover(buttons[2]);
+ await nextRender();
+ expect(tooltip.opened).to.be.false;
+ });
- it('should not set tooltip properties if there is no tooltip', async () => {
- const spyTarget = sinon.spy(menuBar._tooltipController, 'setTarget');
- const spyContent = sinon.spy(menuBar._tooltipController, 'setContext');
- const spyOpened = sinon.spy(menuBar._tooltipController, 'setOpened');
+ it('should hide tooltip on menu bar mouseleave', () => {
+ mouseover(buttons[0]);
+ mouseleave(menuBar);
+ expect(tooltip.opened).to.be.false;
+ });
- tooltip.remove();
- await nextRender();
+ it('should hide tooltip on menu bar container mouseover', () => {
+ mouseover(buttons[0]);
+ mouseover(menuBar._container);
+ expect(tooltip.opened).to.be.false;
+ });
- mouseover(buttons[0]);
+ it('should show tooltip again on menu bar button mouseover', () => {
+ mouseover(buttons[0]);
+ mouseover(menuBar._container);
+ mouseover(buttons[1]);
+ expect(tooltip.opened).to.be.true;
+ });
- expect(spyTarget.called).to.be.false;
- expect(spyContent.called).to.be.false;
- expect(spyOpened.called).to.be.false;
- });
+ it('should set tooltip target on menu button mouseover', () => {
+ mouseover(buttons[0]);
+ expect(tooltip.target).to.be.equal(buttons[0]);
+ });
- it('should not override a custom generator', () => {
- tooltip.generator = () => 'Custom tooltip';
- mouseover(buttons[0]);
- expect(getTooltipText()).to.equal('Custom tooltip');
- });
+ it('should set tooltip context on menu button mouseover', () => {
+ mouseover(buttons[0]);
+ expect(tooltip.context).to.be.instanceOf(Object);
+ expect(tooltip.context.item.text).to.equal('Edit');
+ });
- describe('overflow button', () => {
- beforeEach(async () => {
- // Reduce the width by the width of the last visible button
- menuBar.style.display = 'inline-block';
- menuBar.style.width = `${menuBar.offsetWidth - buttons[2].offsetWidth}px`;
- await nextRender();
- await nextRender();
- // Increase the width by the width of the overflow button
- menuBar.style.width = `${menuBar.offsetWidth + menuBar._overflow.offsetWidth}px`;
- await nextRender();
- await nextRender();
+ it('should change tooltip context on another menu button mouseover', () => {
+ mouseover(buttons[0]);
+ mouseover(buttons[1]);
+ expect(tooltip.context.item.text).to.equal('Share');
});
- it('should not show tooltip on overflow button mouseover', () => {
- mouseover(buttons[buttons.length - 1]);
+ it('should hide tooltip on menu button mousedown', () => {
+ mouseover(buttons[0]);
+ mousedown(buttons[0]);
expect(tooltip.opened).to.be.false;
});
- it('should close tooltip on overflow button mouseover', () => {
+ it('should hide tooltip on mouseleave from overlay to outside', () => {
+ const overlay = tooltip._overlayElement;
mouseover(buttons[0]);
- mouseover(buttons[buttons.length - 1]);
- expect(tooltip.opened).to.be.false;
+ mouseenter(overlay);
+ mouseleave(overlay);
+ expect(overlay.opened).to.be.false;
});
- it('should close tooltip on overflow button keyboard navigation', () => {
+ it('should not show tooltip on focus without keyboard interaction', async () => {
buttons[0].focus();
- arrowRight(buttons[0]);
- expect(tooltip.opened).to.be.true;
- arrowRight(buttons[1]);
+ await nextRender();
expect(tooltip.opened).to.be.false;
});
- it('should not show tooltip on overflow button keyboard focus', () => {
+ it('should show tooltip on menu button keyboard focus', () => {
+ tabKeyDown(document.body);
+ focusin(buttons[0]);
+ expect(tooltip.opened).to.be.true;
+ });
+
+ it('should not show tooltip on another parent menu button focus when open', async () => {
buttons[0].focus();
arrowRight(buttons[0]);
+ arrowDown(buttons[1]);
arrowRight(buttons[1]);
+ await nextRender();
+ expect(tooltip.opened).to.be.false;
+ });
+
+ it('should set tooltip target on menu button keyboard focus', () => {
+ tabKeyDown(document.body);
+ focusin(buttons[0]);
+ expect(tooltip.target).to.be.equal(buttons[0]);
+ });
+
+ it('should set tooltip context on menu button keyboard focus', () => {
tabKeyDown(document.body);
- focusin(buttons[buttons.length - 1]);
+ focusin(buttons[0]);
+ expect(tooltip.context).to.be.instanceOf(Object);
+ expect(tooltip.context.item.text).to.equal('Edit');
+ });
+
+ it('should hide tooltip on menu-bar focusout', () => {
+ tabKeyDown(document.body);
+ focusin(buttons[0]);
+ focusout(menuBar);
expect(tooltip.opened).to.be.false;
});
- });
- describe('open on hover', () => {
- beforeEach(() => {
- menuBar.openOnHover = true;
+ it('should hide tooltip on menuBar menu button content Esc', () => {
+ tabKeyDown(document.body);
+ focusin(buttons[0]);
+ escKeyDown(buttons[0]);
+ expect(tooltip.opened).to.be.false;
});
- it('should show tooltip on mouseover for button without children', () => {
- menuBar.openOnHover = true;
+ it('should set tooltip opened to false when the menuBar is removed', () => {
mouseover(buttons[0]);
- expect(tooltip.opened).to.be.true;
- });
- it('should not show tooltip on mouseover for button with children', () => {
- menuBar.openOnHover = true;
- mouseover(buttons[1]);
+ menuBar.remove();
+
expect(tooltip.opened).to.be.false;
});
- });
- describe('delay', () => {
- const DEFAULT_DELAY = 500;
+ it('should not set tooltip properties if there is no tooltip', async () => {
+ const spyTarget = sinon.spy(menuBar._tooltipController, 'setTarget');
+ const spyContent = sinon.spy(menuBar._tooltipController, 'setContext');
+ const spyOpened = sinon.spy(menuBar._tooltipController, 'setOpened');
+
+ tooltip.remove();
+ await nextRender();
+
+ mouseover(buttons[0]);
+
+ expect(spyTarget.called).to.be.false;
+ expect(spyContent.called).to.be.false;
+ expect(spyOpened.called).to.be.false;
+ });
+
+ it('should not override a custom generator', () => {
+ tooltip.generator = () => 'Custom tooltip';
+ mouseover(buttons[0]);
+ expect(getTooltipText()).to.equal('Custom tooltip');
+ });
+
+ describe('overflow button', () => {
+ beforeEach(async () => {
+ // Reduce the width by the width of the last visible button
+ menuBar.style.display = 'inline-block';
+ menuBar.style.width = `${menuBar.offsetWidth - buttons[2].offsetWidth}px`;
+ await nextRender();
+ await nextRender();
+ // Increase the width by the width of the overflow button
+ menuBar.style.width = `${menuBar.offsetWidth + menuBar._overflow.offsetWidth}px`;
+ await nextRender();
+ await nextRender();
+ });
+
+ it('should not show tooltip on overflow button mouseover', () => {
+ mouseover(buttons[buttons.length - 1]);
+ expect(tooltip.opened).to.be.false;
+ });
- let clock;
+ it('should close tooltip on overflow button mouseover', () => {
+ mouseover(buttons[0]);
+ mouseover(buttons[buttons.length - 1]);
+ expect(tooltip.opened).to.be.false;
+ });
- beforeEach(() => {
- clock = sinon.useFakeTimers({
- shouldClearNativeTimers: true,
+ it('should close tooltip on overflow button keyboard navigation', () => {
+ buttons[0].focus();
+ arrowRight(buttons[0]);
+ expect(tooltip.opened).to.be.true;
+ arrowRight(buttons[1]);
+ expect(tooltip.opened).to.be.false;
+ });
+
+ it('should not show tooltip on overflow button keyboard focus', () => {
+ buttons[0].focus();
+ arrowRight(buttons[0]);
+ arrowRight(buttons[1]);
+ tabKeyDown(document.body);
+ focusin(buttons[buttons.length - 1]);
+ expect(tooltip.opened).to.be.false;
});
});
- afterEach(() => {
- // Wait for cooldown
- clock.tick(DEFAULT_DELAY);
- clock.restore();
+ describe('open on hover', () => {
+ beforeEach(() => {
+ menuBar.openOnHover = true;
+ });
+
+ it('should show tooltip on mouseover for button without children', () => {
+ menuBar.openOnHover = true;
+ mouseover(buttons[0]);
+ expect(tooltip.opened).to.be.true;
+ });
+
+ it('should not show tooltip on mouseover for button with children', () => {
+ menuBar.openOnHover = true;
+ mouseover(buttons[1]);
+ expect(tooltip.opened).to.be.false;
+ });
});
- it('should use hover delay on menu button mouseover', () => {
- tooltip.hoverDelay = 100;
+ describe('delay', () => {
+ const DEFAULT_DELAY = 500;
- mouseover(buttons[0]);
- expect(tooltip.opened).to.be.false;
+ let clock;
- clock.tick(100);
- expect(tooltip.opened).to.be.true;
+ beforeEach(() => {
+ clock = sinon.useFakeTimers({
+ shouldClearNativeTimers: true,
+ });
+ });
+
+ afterEach(() => {
+ // Wait for cooldown
+ clock.tick(DEFAULT_DELAY);
+ clock.restore();
+ });
+
+ it('should use hover delay on menu button mouseover', () => {
+ tooltip.hoverDelay = 100;
+
+ mouseover(buttons[0]);
+ expect(tooltip.opened).to.be.false;
+
+ clock.tick(100);
+ expect(tooltip.opened).to.be.true;
+ });
+
+ it('should use hide delay on menu button mouseleave', () => {
+ tooltip.hideDelay = 100;
+
+ mouseover(buttons[0]);
+ clock.tick(DEFAULT_DELAY);
+
+ mouseleave(menuBar);
+ expect(tooltip.opened).to.be.true;
+
+ clock.tick(100);
+ expect(tooltip.opened).to.be.false;
+ });
+
+ it('should not use hide delay on menu button mousedown', () => {
+ tooltip.hideDelay = 100;
+
+ mouseover(buttons[0]);
+ clock.tick(DEFAULT_DELAY);
+
+ mousedown(buttons[0]);
+ expect(tooltip.opened).to.be.false;
+ });
+
+ it('should use focus delay on menu button keyboard focus', () => {
+ tooltip.focusDelay = 100;
+
+ tabKeyDown(document.body);
+ focusin(buttons[0]);
+ expect(tooltip.opened).to.be.false;
+
+ clock.tick(100);
+ expect(tooltip.opened).to.be.true;
+ });
+
+ it('should not use hide delay on menu button Esc', () => {
+ tooltip.hideDelay = 100;
+
+ tabKeyDown(document.body);
+ focusin(buttons[0]);
+ clock.tick(DEFAULT_DELAY);
+
+ escKeyDown(buttons[0]);
+ expect(tooltip.opened).to.be.false;
+ });
});
+ });
- it('should use hide delay on menu button mouseleave', () => {
- tooltip.hideDelay = 100;
+ describe('focusable disabled button', () => {
+ before(() => {
+ window.Vaadin.featureFlags ??= {};
+ window.Vaadin.featureFlags.focusableDisabledComponents = true;
+ });
- mouseover(buttons[0]);
- clock.tick(DEFAULT_DELAY);
+ after(() => {
+ window.Vaadin.featureFlags.focusableDisabledComponents = false;
+ });
- mouseleave(menuBar);
- expect(tooltip.opened).to.be.true;
+ beforeEach(async () => {
+ menuBar = fixtureSync(
+ `
+
+
+
+
+
`,
+ ).firstElementChild;
+
+ menuBar.items = [
+ { text: 'Edit' },
+ {
+ text: 'Copy',
+ tooltip: 'Copy tooltip',
+ disabled: true,
+ },
+ ];
- clock.tick(100);
- expect(tooltip.opened).to.be.false;
+ await nextRender();
+ buttons = menuBar._buttons;
+
+ tooltip = menuBar.querySelector('vaadin-tooltip');
});
- it('should not use hide delay on menu button mousedown', () => {
- tooltip.hideDelay = 100;
+ afterEach(async () => {
+ await resetMouse();
+ });
- mouseover(buttons[0]);
- clock.tick(DEFAULT_DELAY);
+ it('should toggle tooltip on disabled button hover', async () => {
+ const { x, y } = middleOfNode(buttons[1]);
+ await sendMouse({ type: 'move', position: [Math.floor(x), Math.floor(y)] });
+ expect(getTooltipText()).to.equal('Copy tooltip');
- mousedown(buttons[0]);
- expect(tooltip.opened).to.be.false;
+ await sendMouse({ type: 'move', position: [0, 0] });
+ expect(getTooltipText()).to.be.null;
});
- it('should use focus delay on menu button keyboard focus', () => {
- tooltip.focusDelay = 100;
+ it('should toggle tooltip on disabled button focus when navigating with arrow keys', async () => {
+ await sendKeys({ press: 'Tab' });
+ expect(getTooltipText()).to.be.null;
- tabKeyDown(document.body);
- focusin(buttons[0]);
- expect(tooltip.opened).to.be.false;
+ await sendKeys({ press: 'ArrowRight' });
+ expect(getTooltipText()).to.equal('Copy tooltip');
- clock.tick(100);
- expect(tooltip.opened).to.be.true;
+ await sendKeys({ press: 'ArrowLeft' });
+ expect(getTooltipText()).to.be.null;
});
- it('should not use hide delay on menu button Esc', () => {
- tooltip.hideDelay = 100;
+ it('should toggle tooltip on disabled button focus when navigating with Tab', async () => {
+ menuBar.tabNavigation = true;
- tabKeyDown(document.body);
- focusin(buttons[0]);
- clock.tick(DEFAULT_DELAY);
+ await sendKeys({ press: 'Tab' });
+ expect(getTooltipText()).to.be.null;
- escKeyDown(buttons[0]);
- expect(tooltip.opened).to.be.false;
+ await sendKeys({ press: 'Tab' });
+ expect(getTooltipText()).to.equal('Copy tooltip');
+
+ await sendKeys({ down: 'Shift' });
+ await sendKeys({ press: 'Tab' });
+ await sendKeys({ up: 'Shift' });
+ expect(getTooltipText()).to.be.null;
});
});
});