sparklemotion / mechanize

Mechanize is a ruby library that makes automated web interaction easy.
https://www.rubydoc.info/gems/mechanize/
MIT License
4.39k stars 473 forks source link

Is there a way to fill in fields that aren't inside a form tag and click on elements that aren't links? #591

Closed randall-coding closed 2 years ago

randall-coding commented 2 years ago

From reading the docs, it seems that in order to fill in the value of an input field that field must be inside a form tag and to click on an element that element needs to be a link.

In my current use case I need to break both of those rules, the input field is not in a form and the element to click on is not a link. Any help is greatly appreciated.

flavorjones commented 2 years ago

Hi @Randall-Coding, thanks for asking this question. I'll try to help.

Can you provide an HTML snippet that demonstrates the form and fields that you're operating on? I've found that grounding the discussion in a concrete example is usually very helpful.

I'll take some guesses at what you're working with ...

input field not inside a form tag

Without more information, I suspect what you're seeing is an input field that is not contained within the form tag, but is using the form attribute to declare its association with that form. Does that sound right?

If that's right, then the underlying issue is that Mechanize hasn't been kept up-to-date with the HTML5 spec (which has been constantly changing over the past 10+ years). If you peek at lib/mechanize/form.rb you'll see the parse method only searches for input fields within the form's DOM subtree and not elsewhere in the document as described in the form attribute docs I hyperlinked above.

click on an element that's not a link

This one is a bit stranger -- I would like to understand your specific use case more deeply. You can try to do this by using Mechanize#click which tries to do the right thing (if the element has an href or src attribute it will follow that URI).

But it seems more likely that the page you're working with relies on Javascript to make an element clickable in the browser, and/or traps the click event to trigger a Javascript callback. Mechanize isn't a full browser, and it doesn't attempt to do anything with Javascript that a browser might normally load. If this is what you're dealing with, you may want to use a tool that will leverage actual browser functionality, like capybara which uses Selenium and something like Chromedriver to load the page in a headless browser. Capybara is more complicated to use, and slower than Mechanize, but in return you get 100% of browser functionality.

Let me know if anything here is helpful, or if I've made incorrect assumptions.

flavorjones commented 2 years ago

I've created #592 to track missing HTML5 functionality.

randall-coding commented 2 years ago

@flavorjones Thanks for the response. Yes it turns out the page is using javascript and in fact angular. I ended up switching over to Selenium.