rubycdp / ferrum

Headless Chrome Ruby API
https://ferrum.rubycdp.com
MIT License
1.71k stars 123 forks source link

Click on chrome invisible element not work. #225

Closed zw963 closed 6 months ago

zw963 commented 2 years ago

Following is a example.

image

I want to click on all of "全部" in the scroll view, but only 4 of them available, there left 16 "全部" invisible, for make left ones visible, use can move scroll bar or use keyboard page down.

That is, i can find out full 20 "全部" element use click_node = popup.xpath('.//span[contains(text(), "全部")]'), but only 4 of them can click, others is not clickable, for now, i have to trigger keyboard like this:

while click on invisbile element failed  # try click again.
  instance.keyboard.type(:pagedown)
  sleep 
end

but this solution is is crisp , and error-prone, behavior not controllable.

I don't sure if this is a issue, because i think any element which can retrieve, it should accept browser click event.

Anyway, if this is not a issue, is there exists a robust way to make one invisible element can be visible? (move scroll bar automatically), or do a function, check one element is visible?

Thank you.

route commented 2 years ago

It should have worked, I'll take a look

zw963 commented 2 years ago

It should have worked, I'll take a look

Hi, @route, AFAIK, only poltergeist driver for capybara support click on hidden element, when i switch to selenium which use chrome headless with capybara, it not work anymore, it seem like chrome not permit this?

But, i am not ensure this, because i test those one or two years ago, and don't sure if same cases as this.

route commented 2 years ago

I think if you use Cuprite driver it might work because Ferrum appeared from it, and now we are in transition of things from Cuprite to Ferrum and back. First of all there's trigger(:click) method there, and second it uses some JS to move node into viewport before clicking, Ferrum is more straightforward and doesn't do anything for now. But it's on my todo list

zw963 commented 2 years ago

I think if you use Cuprite driver it might work because Ferrum appeared from it, and now we are in transition of things from Cuprite to Ferrum and back. First of all there's trigger(:click) method there, and second it uses some JS to move node into viewport before clicking, Ferrum is more straightforward and doesn't do anything for now. But it's on my todo list

It works when use cuprite with capybara, quite well, tough, i guess this is a feature of capybara, not cuprite, right?

I will keep this issue open, if we have plan add this feature to ferrum, capybara is too heavy, introduce many gems, in fact, only several feature need use capybara.

  1. check on wrong link after pop view is show, which cause open a new link in new tab, i don't know way, add wait_for_idle or stop_moving both not working, change slowmo option or FERRUM_NODE_MOVING_WAIT,FERRUM_NODE_MOVING_ATTEMPTS optins, both not working, maybe need more research.

  2. click on invisible element manually use keyboard pagedown, it buggy, perhaps above 1 caused by this, anyway, capybara works!

anyway, i will back if ferrum support this.

Nakilon commented 2 years ago

In my opinion you should scroll to element explicitely. Ferrum should not do that for you. I'm not sure I want the page to scroll without my knowledge.

route commented 2 years ago

In my opinion you should scroll to element explicitely. Ferrum should not do that for you. I'm not sure I want the page to scroll without my knowledge.

That's exactly my initial thought, Ferrum does things straightforward, no magic. Cuprite is compatible with the other drivers and has some magic inside because in Capybara you click_link and a lot of things happen. I think we can move those little missing pieces from Cuprite but we should never use them as hidden behavior on click, you should do them explicitly.

zw963 commented 2 years ago

In my opinion you should scroll to element explicitely.

Hi, How to check one node is visible by user? could you please give me some clue?

for now. if not use capybara, my solution is quite naive, i have to write a loop to

click popup menu, try lick
click popup menu, page down, try click 
click popup  menu, page down, page down, try click
...

Is a better way to archive this? or, should we have a api like: node.visible??

Mifrill commented 2 years ago

@zw963

How to check one node is visible by user?

Maybe this may help: https://github.com/rubycdp/ferrum/pull/141

We can try using this CDP command to click on invisible elements: https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-scrollIntoViewIfNeeded

By the way, it is implemented in Cuprite, so you can, probably, try Cuprite: https://github.com/rubycdp/cuprite/blob/749805654986d832554ffd17bb3f190159ed2b3e/lib/capybara/cuprite/javascripts/index.js#L256-L271

zw963 commented 2 years ago

@zw963

How to check one node is visible by user?

Maybe this may help: #141

We can try using this CDP command to click on invisible elements: https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-scrollIntoViewIfNeeded

By the way, it is implemented in Cuprite, so you can, probably, try Cuprite: https://github.com/rubycdp/cuprite/blob/749805654986d832554ffd17bb3f190159ed2b3e/lib/capybara/cuprite/javascripts/index.js#L256-L271

If this API? please check screenshot.

image

In fact, when use Cuprite with Capybara, it always work before because Capybara have this functionality, right?

so, i consider it meanful only can be use on Ferrum directly.

Mifrill commented 2 years ago

If this API? please check screenshot.

correct.

it always work before because Capybara have this functionality, right?

yes, but it uses cuprite underneath as driver: https://github.com/rubycdp/cuprite/blob/749805654986d832554ffd17bb3f190159ed2b3e/lib/capybara/cuprite/page.rb#L95-L96

zw963 commented 2 years ago

yes, but it uses cuprite underneath as driver:

Hi, Is there a way to port this feature into ferrum directly? i consider capybara is a little heavy, many feature never use it anyway.

      evaluate_on(node: node, expression: "_cuprite.scrollIntoViewport(this)")
Mifrill commented 2 years ago

Is there a way to port this feature into ferrum directly?

we wanna keep ferrum as simple as possible:

ferrum instead should be close to what real user would do with the browser. So if you can't see a node in the viewport you can't click on it,

https://github.com/rubycdp/ferrum/pull/141#discussion_r561893810

However, I think, it's nice to have Ferrum::Node#in_viewport? and Ferrum::Node#scroll_into_view methods to have a simpler way to handle it without additional cuprite logic.

sandstrom commented 6 months ago

I'm doing some issue gardening 🌱🌿 🌷 and came upon this issue. Since it's quite old and doesn't seem like a problem with Ferrum (just that OP wants something that is handled by Cuprite). Maybe we can close this issue?

By closing some old issues we reduce the list of open issues to a more manageable set.

zw963 commented 6 months ago

Feel free to close issue, thanks.

sandstrom commented 6 months ago

@zw963 I cannot. You are the author, you can close it though.

Nakilon commented 5 months ago

Also see https://stackoverflow.com/a/72717388/322020

Chrome 105 (and Edge and Opera) and Firefox 106 introduced Element.checkVisibility() which returns true if the element is visible, and false otherwise.