The Olly Bee
The Olly Bee

Reputation: 71

Playwright - how to hover over an element for 5 seconds

I was wondering if anyone could help me out. I'm using hover in playwright but I need to hover over the specified element and wait for 4 seconds

I looked through the docs https://playwright.dev/docs/api/class-page#page-hover and I couldn't find anything about adding some sort of delay on hover

The reason why I want to do this is because at a 4 second hover we show a tooltip with some additional information that pops up

Upvotes: 6

Views: 31730

Answers (5)

ggorlen
ggorlen

Reputation: 57185

This might be an XY problem because you'd typically wait for the next text to appear rather than using timing on the hover. If this doesn't work, please share your page under test and full code.

Here's a complete demonstration of testing the following "tooltip" (yes, there is no styling or positioning, but that's irrelevant):

let tid;
const tooltip = document.createElement("p");
const p = document.querySelector("p");
p.addEventListener("mouseenter", event => {
  tid = setTimeout(() => {
    tooltip.textContent = "first tooltip";
    document.body.append(tooltip);
    tid = setTimeout(() => {
      tooltip.textContent = "second tooltip";
    }, 3000);
  }, 1000);
});
p.addEventListener("mouseout", event => {
  tooltip.remove();
  clearTimeout(tid);
});
p {
  border: 1px solid black;
}
<p>hover me</p>

The page has a paragraph that you can hover to show one tooltip after 1 second, then the tooltip changes after 4 seconds (a second one popping up could be tested in the same way).

Here's the test:

import {expect, test} from "@playwright/test"; // ^1.42.1

const html = `<p>hover me</p>
<script>
let tid;
const tooltip = document.createElement("p");
const p = document.querySelector("p");
p.addEventListener("mouseenter", event => {
  tid = setTimeout(() => {
    tooltip.textContent = "first tooltip";
    document.body.append(tooltip);
    tid = setTimeout(() => {
      tooltip.textContent = "second tooltip";
    }, 3000);
  }, 1000);
});
p.addEventListener("mouseout", event => {
  tooltip.remove();
  clearTimeout(tid);
});
</script>`;

test("two tooltips show on paragraph hover, then disappear", async ({page}) => {
  await page.setContent(html);
  const tooltip1 = page.getByText("first tooltip");
  const tooltip2 = page.getByText("second tooltip");
  await expect(tooltip1).not.toBeVisible();
  await expect(tooltip2).not.toBeVisible();
  await page.getByText("hover me").hover();
  await expect(tooltip2).not.toBeVisible();
  await expect(tooltip1).toBeVisible();
  await expect(tooltip1).not.toBeVisible();
  await expect(tooltip2).toBeVisible();

  // or something like await page.mouse.move(0, 0); to drop hover
  await page.locator("body").hover();
  await expect(tooltip1).not.toBeVisible();
  await expect(tooltip2).not.toBeVisible();
});

You can see that no timeouts or delays are needed. Just assert the state and let Playwright handle waiting for you.

Upvotes: 0

Amol Chavan
Amol Chavan

Reputation: 3980

Try dispatchEvent API provided by Playwright.

const elementHandle = await page.getByText(locatorText);
const eventType = 'mouseover';  // String representing the event type
await elementHandle.dispatchEvent(eventType);

Upvotes: 1

Assi.NET
Assi.NET

Reputation: 472

I was able to solve the issue of the tooltip by hovering at different places of the element that needed to be hovered. Anything else just does not work. At one point you will identify the pattern for the tooltip to appear. For example which 2 positions are needed to trigger the toolbox with 1 attempt.

Consider that in your case maybe you need to adjust the position differently. Maybe playing with X, then Y, perhaps a combination of both. To get an idea of how many pixels are resealable - consider downloading a pixel ruler and measuring your 'box' of the element. You can invoke as well my_element.highlight() and run in a headed mode to visualize the issue.

    import random

    for _ in range(50):
        rand_int = random.randint(0, 30)
        print(f"Random number: {rand_int}")
        my_element.hover(position={'x':10.0, 'y':rand_int})

Upvotes: 3

Jaky Ruby
Jaky Ruby

Reputation: 1654

I think Hover should be enough as @kozko suggested

page.hover('YourSelectorToBeHovered')
page.waitForSelector("YourSelectorOfYourTooltipOnceIsOpen")

In case that is not enough for you, you could also try click with delay param:

delay: <float> Time to wait between mousedown and mouseup in milliseconds. Defaults to 0.

page.click('YourSelector', delay=5000)
page.waitForSelector("YourSelectorOfYourTooltipOnceIsOpen")

Click - Official playwright

Upvotes: 5

kozko
kozko

Reputation: 31

You could use waitForSelector with the tooltip after the hover for it to start waiting until your tooltip appears.

It could be problematic depending on where the hover takes place because the tooltip can appear on the mouse location which could lead to it disappearing depending on the code

Upvotes: 1

Related Questions