Skip to content

Conversation

@ChristianDavis
Copy link
Contributor

Waits for a selector to be present and hidden, opposite behavior of the option visible.

@JoelEinbinder
Copy link
Contributor

I'm curious as to what the use case for this is.

@ChristianDavis
Copy link
Contributor Author

I'm using it for a screen where a modal is covering a button, click doesn't work till the modal is hidden

@ebidel
Copy link
Contributor

ebidel commented Oct 6, 2017

It's really hard to determine proper visibility of an element. For example, these checks fail if an ancestor node has display: none. The node will still report itself as "visible".

I almost wish waitForSelector didn't have a visible option to begin with. There's too many gotchas around visibility of dom nodes.

@ChristianDavis
Copy link
Contributor Author

@ebidel I agree, it's tricky. And it doesn't take opacity into account, but I haven't seen any implementations that consider opacity. But, I disagree that it should be left out. Developer time being the most valuable asset, visibility is an easy way to time events on a page that might be complicated otherwise.

I added reverse and hidden options around the visible feature, both options visible and hidden climb the DOM to check for a hidden ancestor. #549

if the options visible or hidden are used, the waitForSelector function
climbs up the DOM to check if each parent is display:none.
@trevordmiller
Copy link

I'm using await page.waitFor(() => !document.querySelector("{selector}")); for this now, but would appreciate some sort of reverse option on waitForSelector.

@aslushnikov
Copy link
Contributor

Hey @ChristianDavis, thanks for the PR.

I like the hidden option:

await page.waitForSelector('.dialog', {hidden: true});

However, I'd love it to be a full opposite of visible option, i.e. to wait for element to be either absent from DOM or having display: none or visibility: hidden.

I don't like the reverse option. It's confusing if there's both visible: true and reverse: true: is it a hidden: true now?

I'd like to scope this PR to only add a hidden option. Let me know how you feel about this.

@ChristianDavis
Copy link
Contributor Author

@aslushnikov yeah, looks confusing. Someone had pointed out that webdriverio has an implementation { reverse: true }, but I should just combine the functionality into hidden

@ChristianDavis
Copy link
Contributor Author

{hidden: true} checks for NOT present, or hidden, or ancestors hidden

@aslushnikov
Copy link
Contributor

@ChristianDavis This PR now seems to be doing two things:

  1. Adding 'hidden' option which is opposite to the 'visible'
  2. Changing 'visible' and 'hidden' options to traverse the hierarchy to check for visibility.

Could you please split the PR into two separate ones? This will make for a nicer history and smaller diffs. Also, I feel like we've agreed on 'hidden' option, but there might be some questions on the hierarchy traversal.

@ChristianDavis
Copy link
Contributor Author

@ebidel didn't think hidden OR visible makes sense without the ancestor check, and that's probably true. But I could split it up

@ebidel
Copy link
Contributor

ebidel commented Oct 11, 2017

My point was really that checking "visibility" is hard to get right and we should consider removing the option. But may people like the convenience and it's pretty nice for the simpler cases.

I'm a fan of making the existing checks more reliable. So traversing the DOM to check ancestors makes sense to me. To save some work, you could also cut out early in the case of element.offsetParent === null. That'd let you know if the element (or any ancestor) is display: none.

Splitting these up into separate PRs sgtm.

Dropped the ancestor check
@ChristianDavis
Copy link
Contributor Author

feature is now just the hidden option, waits for not present or hidden

return style && style.display !== 'none' && style.visibility !== 'hidden';
if (waitForVisible)
return style && style.display !== 'none' && style.visibility !== 'hidden';
return style && (style.display === 'none' || style.visibility === 'hidden');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically the !style makes more sense here.

How about:

const style = window.getComputedStyle(node);
const isVisible = style && style.display !== 'none' && style.visibility !== 'hidden';
return waitForVisible === isVisible;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks better

return ( waitForVisible === isVisible || waitForHidden === !isVisible);

test/test.js Outdated
it('hidden should wait for visibility: hidden', SX(async function() {
let divHidden = false;
await page.setContent(`<div style='display: block;'></div>`);
expect(divHidden).toBe(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit - here and in other tests: please drop this check, it's a noop

@aslushnikov aslushnikov merged commit 8511db9 into puppeteer:master Oct 13, 2017
@aslushnikov
Copy link
Contributor

@ChristianDavis thanks!

@ChristianDavis ChristianDavis deleted the feat/hidden branch October 13, 2017 16:14
@trevordmiller
Copy link

@aslushnikov When will this be released to npm?

@vsemozhetbyt
Copy link
Contributor

Is this valid for frame.waitForSelector(selector[, options])? If so, the doc addition seems missing.

@ChristianDavis
Copy link
Contributor Author

@vsemozhetbyt You're right, I didn't notice that. Page.waitfor is actually just abstracting the frame implementation. Maybe the options for the frame.waitFor could be linked, or vice versa?

@vsemozhetbyt
Copy link
Contributor

I am not sure, but it seems all the other descriptions are copied when similar.

@aslushnikov
Copy link
Contributor

@ChristianDavis we copy descriptions: it's less clicks for users to navigate documentation.

ithinkihaveacat pushed a commit to ithinkihaveacat/puppeteer that referenced this pull request Oct 31, 2017
This patch adds a 'hidden' option for the `page.waitForSelector` method.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants