bobbie_j
bobbie_j

Reputation: 25

WATIR: Is there a reason why browser scrolling won't work?

I'm trying to use browser.scroll.to :bottom but nothing happens. I know that it works because I've tried it on public facing sites such as the BBC and Wikipedia, but for some reason, these scroll commands don't work on our in-house browser based app.

Does anyone know of any reasons or settings that could be preventing this from happening? Things such as browser.refresh and browser.window.maximize work fine but the scrolling literally refuses to budge.

Here's what my code looks like:

require 'watir'
require_relative 'regression_config_bob01.rb'
require 'date'
require 'faker'
require 'slack-notifier'
require 'watir-scroll'

user_name = "blah"
password = "blah"

test_env = "the Site"


browser = Watir::Browser.new 

browser.goto(test_env)

# Login
browser.text_field(:name => 'P101_USERNAME').set user_name
browser.text_field(:tabindex=> '2').set password
browser.link(:text => "Log in").click

sleep 20

browser.wd.action.scroll_by(0, 1000).perform # Suggested Scroll line

print "done"

sleep 30

temporary_exp.rb:62:in <main>': undefined method scroll_by' for #<Selenium::WebDriver::W3CActionBuilder:0x000000014ac54bd0 @bridge=#<Selenium::WebDriver::Remote::W3C::Bridge:0x000000014ac1e440 @capabilities=#<Selenium::WebDriver::Remote::W3C::Capabilities:0x000000014ac1e940 @capabilities={:proxy=>nil, :browser_name=>"chrome", :browser_version=>"106.0.5249.119", :platform_name=>"mac os x", :accept_insecure_certs=>false, :page_load_strategy=>"normal", :implicit_timeout=>0, :page_load_timeout=>300000, :script_timeout=>30000, :remote_session_id=>nil, :accessibility_checks=>nil, :profile=>nil, :rotatable=>nil, :device=>nil, "chrome"=>{"chromedriverVersion"=>"105.0.5195.52 (412c95e518836d8a7d97250d62b29c2ae6a26a85-refs/branch-heads/5195@{#853})", "userDataDir"=>"/var/folders/hb/h_0h2t79183fkkppsr6r19nc0000gn/T/.com.google.Chrome.BV85VD"}, "goog:chromeOptions"=>{"debuggerAddress"=>"localhost:50818"}, "networkConnectionEnabled"=>false, "setWindowRect"=>true, "strictFileInteractability"=>false, "unhandledPromptBehavior"=>"dismiss and notify", "webauthn:extension:credBlob"=>true, "webauthn:extension:largeBlob"=>true, "webauthn:virtualAuthenticators"=>true}>, @session_id="8c59128dd44054681f62819d2fed25cf", @http=#<Watir::HttpClient:0x000000014ab6e298 @open_timeout=60, @read_timeout=nil, @server_url=#<URI::HTTP http://127.0.0.1:9515/>, @proxy=nil, @http=#<Net::HTTP 127.0.0.1:9515 open=true>>, @file_detector=nil, @escaper=#URI::RFC2396_Parser:0x000000014b0cbbc8, @manage=#<Selenium::WebDriver::W3CManager:0x000000014ab640b8 @bridge=#<Selenium::WebDriver::Remote::W3C::Bridge:0x000000014ac1e440 ...>, @window=#<Selenium::WebDriver::Window:0x000000014aa17ca0 @bridge=#<Selenium::WebDriver::Remote::W3C::Bridge:0x000000014ac1e440 ...>>>>, @devices=[#<Selenium::WebDriver::Interactions::PointerInput:0x000000014ac54f40 @name="mouse", @actions=[], @kind=:mouse>, #<Selenium::WebDriver::Interactions::KeyInput:0x000000014ac54d38 @name="keyboard", @actions=[]>], @async=false> (NoMethodError)

Upvotes: 0

Views: 197

Answers (2)

titusfortner
titusfortner

Reputation: 4194

The current scroll implementation is using javascript to move the page around. For some reason your app is not responding to the JS commands in the normal way.

Selenium has recently released native scrolling via the drivers that Watir has not yet been updated. Take a look at the Selenium documentation on it: https://www.selenium.dev/documentation/webdriver/actions_api/wheel/?language=ruby

To use this in watir, you just need to add the line to the top: driver = browser.wd

So to scroll down by 2000 pixels, you can do:

driver = browser.wd
driver.action
      .scroll_by(0, 2000)
      .perform

Upvotes: 1

Luka Vladika
Luka Vladika

Reputation: 76

like Titus said, Watir is a wrapper for Selenium and lets you write shorter and prettier code, like

browser.scroll.to :bottom
browser.scroll.to :top
browser.element(id: "asd").scroll.to

but when (for any reason) it doesn't work you can use Selenium syntax directly by sending commands to browser.wd instead browser like this:

browser.wd.action.scroll_by(0, 1000).perform #this scrolls bottom
browser.wd.action.scroll_by(0, -1000).perform #this scrolls top  
browser.wd.action.scroll_to(browser.wd.find_element(id: "asd")).perform

but instead of writing browser.wd every time you need to talk to driver directly, you can type driver = browser.wd so your code is more clear:

driver = browser.wd
driver.action.scroll_by(0, 1000).perform #this scrolls bottom
driver.action.scroll_by(0, -1000).perform #this scrolls top  
some_element = driver.find_element(id: "asd")
driver.action.scroll_to(some_element).perform

There are countless examples where using Watir is more efficient than talking to driver directly, you just happened to encounter an edge case.

Also try avoiding sleep when possible, instead, wait for something to show, like:

browser.element(id: 'asd').wait_until(&:present?)
browser.element(id: 'asd').wait_until({ |el| el.text == "Success" })
some_element = browser.element(id: 'asd')
browser.wait_until(30){some_element.present?}

Instead of .element you can use correct subclass like .div, .button, .span etc

Upvotes: 0

Related Questions