playwright icon indicating copy to clipboard operation
playwright copied to clipboard

[Feature] add `locator.waitForTransition()`

Open janosh opened this issue 3 years ago • 35 comments

I'd like to test computedStyles and visibility after some CSS transition (triggered by user input) finishes. From https://github.com/microsoft/playwright/issues/4055, it seems this is a common but unsupported use case.

const dropdown = await page.locator('.dropdown').

closeDropdown()
await dropdown.waitForTransition() // waitForElementState('stable') doesn't work if the element stays in place

expect(dropdown).toBeHidden()

janosh avatar Jul 14 '22 16:07 janosh

You can probably use getAnimations and check if all/some of the animations have finished. Something like this:

const dropdown = await page.locator('.dropdown').

closeDropdown()
await dropdown.evaluate(e => Promise.all(e.getAnimations({ subtree: true }).map(animation => animation.finished)));

expect(dropdown).toBeHidden()

Will that work for you?

yury-s avatar Jul 14 '22 21:07 yury-s

Wonderful, that does exactly what I need!

I use it in several places so wrapped it in a waitForAnimationEnd helper function:

import type { Page } from '@playwright/test'

function waitForAnimationEnd(page: Page, selector: string) {
  return page
    .locator(selector)
    .evaluate((element) =>
      Promise.all(
        element
          .getAnimations()
          .map((animation) => animation.finished)
      )
    )
}


test(`dropdown is hidden when reaching maxSelect items`, async ({ page }) => {
  await wait_for_animation_end(page, `div.dropdown`)

  expect(await page.locator(`div.dropdown`)).toBeHidden()
  expect(await page.getAttribute(`div.dropdown`, `class`)).toContain(`hidden`)
})

Would it make sense to have a waitForAnimationEnd method in @playwright/test?

janosh avatar Jul 15 '22 09:07 janosh

I need to have this feature too. Thanks for the hints!

alvipeo avatar Jul 15 '22 16:07 alvipeo

We can add a sugar API for this if there is enough interest, leaving this request open to see if there is enough demand.

yury-s avatar Jul 16 '22 01:07 yury-s

Interestingly, I tried yesterday to use the waitForAnimationEnd() helper and it didn't work for angular material sidenav... Either I did not really understand the case or it doesn't work in that case. I ended up with a simple 400 msec timeout (just to be sure the animation is over). And yes, this is probably the best solution in my case as I'm not testing the animation itself.

alvipeo avatar Jul 16 '22 08:07 alvipeo

I would also find this feature useful

JeremieBourque1 avatar Aug 10 '22 14:08 JeremieBourque1

Does this work with elements animated with react-spring?

skysantoroa avatar Aug 31 '22 09:08 skysantoroa

+1 to add this feature

niyarlatotep avatar Nov 10 '22 08:11 niyarlatotep

+1

kawaii-flesh avatar Nov 10 '22 08:11 kawaii-flesh

+1, copying the helper into my code now to use in the meantime

bkfarnsworth avatar Nov 18 '22 22:11 bkfarnsworth

+1

Piero87 avatar Nov 21 '22 11:11 Piero87

+1

juniorerico avatar Dec 02 '22 09:12 juniorerico

+1

MrCliff avatar Dec 16 '22 10:12 MrCliff

+1 for this functionality, it should help us a lot avoiding evaluating timeouts / waits...

tomdelahaba avatar Dec 21 '22 15:12 tomdelahaba

Please +1 the issue on top, that's what is used when we are prioritizing the issues.

pavelfeldman avatar Dec 22 '22 22:12 pavelfeldman

Wonderful, that does exactly what I need!

I use it in several places so wrapped it in a waitForAnimationEnd helper function:

import type { Page } from '@playwright/test'

function waitForAnimationEnd(page: Page, selector: string) {
  return page
    .locator(selector)
    .evaluate((element) =>
      Promise.all(
        element
          .getAnimations()
          .map((animation) => animation.finished)
      )
    )
}


test(`dropdown is hidden when reaching maxSelect items`, async ({ page }) => {
  await wait_for_animation_end(page, `div.dropdown`)

  expect(await page.locator(`div.dropdown`)).toBeHidden()
  expect(await page.getAttribute(`div.dropdown`, `class`)).toContain(`hidden`)
})

Would it make sense to have a waitForAnimationEnd method in @playwright/test?

In my case animations is empty, but if I do this:

await this.page.evaluate('$.timers.length')

it works like that:

2 // $.timers.length
2
2
2
{ x: 243, y: 165, width: 349, height: 24 } // my element bounds
{ x: 243, y: 165, width: 349, height: 24 }
{ x: 243, y: 165, width: 349, height: 24 }
{ x: 243, y: 169, width: 349, height: 24 }
{ x: 243, y: 173, width: 349, height: 24 }
{ x: 243, y: 177, width: 349, height: 24 }
2
2
2
2
2
2
2
{ x: 243, y: 189, width: 349, height: 24 }
{ x: 243, y: 190, width: 349, height: 24 }
{ x: 243, y: 192, width: 349, height: 24 }
{ x: 243, y: 192, width: 349, height: 24 }
{ x: 243, y: 192, width: 349, height: 24 }
{ x: 243, y: 192, width: 349, height: 24 }
{ x: 243, y: 192, width: 349, height: 24 }
{ x: 243, y: 192, width: 349, height: 24 }
{ x: 243, y: 192, width: 349, height: 24 }
{ x: 243, y: 192, width: 349, height: 24 }
{ x: 243, y: 192, width: 349, height: 24 }
{ x: 243, y: 192, width: 349, height: 24 }
{ x: 243, y: 192, width: 349, height: 24 }
{ x: 243, y: 192, width: 349, height: 24 }
{ x: 243, y: 192, width: 349, height: 24 }
0
0
0
0

denkorz avatar Dec 29 '22 12:12 denkorz

@yury-s This issue sits at 20 upvotes. Curious what the threshold for entry is?

janosh avatar Jan 28 '23 14:01 janosh

+1 for this feature. As we face this issue frequently.

manojatlas avatar Feb 07 '23 04:02 manojatlas

+1

VikramSinghMTL avatar Mar 25 '23 18:03 VikramSinghMTL

+1

sirganya avatar Apr 10 '23 14:04 sirganya

+1

ValorHeart avatar May 21 '23 15:05 ValorHeart

+1

381181295 avatar May 23 '23 02:05 381181295

+1

AlexKFU avatar May 31 '23 17:05 AlexKFU

+1

remkoboschker avatar Jun 27 '23 08:06 remkoboschker

+1 I think this very necessary feature it's helps binding wait instead of blind wait

ngocdd avatar Jul 01 '23 06:07 ngocdd

+1

RuanAlesi avatar Aug 16 '23 08:08 RuanAlesi

+1

theniceangel avatar Aug 25 '23 13:08 theniceangel

+1

amit-ash avatar Sep 28 '23 14:09 amit-ash

+1

sajaghori avatar Oct 02 '23 14:10 sajaghori

+1

elimccoy avatar Oct 03 '23 16:10 elimccoy