Selenium Webdriver can't find "navigate" element in Ruby - ruby

I am new to this so it may be obvious, but I am struggling with getting my test to run the "navigate" element. Or Object. Whatever it is. Here is my code:
require "selenium-webdriver"
require "rspec"
# TEST: Sign up for blog
describe "Blog application" do
describe "signup to the blog application" do
it "confirm that a user can successfully signup" do
driver = Selenium::WebDriver::Firefox
# Go to signup form
driver.get "https://selenium-blog.herokuapp.com/signup"
# Fill out and submit form
username_field = driver.find_element(id: 'user_username')
username_field.send_keys("user")
There's more to this test but it isn't relevant to my question. What am I missing? Do I need to install another gem or driver? I've searched everywhere for this answer and can't find it.
I've also tried running it with:
driver.navigate.go
and that fails as well. Says it cannot find the "navigate" element.
Thanks for your help!

You are missing initializing of your wanted web driver. However you didn't post your current version of selenium, so I assumed it was last version.
Here is what documentation says about Selenium::WebDriver.
.for(browser) ⇒ Driver
.for(browser, opts) ⇒ Driver
Create a new Driver instance with the correct bridge for the given browser
One special argument is not passed on to the bridges, :listener. You can pass a listener for this option to get notified of WebDriver events. The passed object must respond to #call or implement the methods from AbstractEventListener.
So in your case you need to change you driver variable
driver = Selenium::WebDriver.for(:firefox)
# ...
WebDriver docs

Here is the simple code which should help you
require 'selenium-webdriver'
driver=Selenium::WebDriver.for :firefox
driver.navigate.to("https://www.google.com/")

Related

How do I use my own cookies in capybara?

I'm trying to (ab)use the capybara web testing framework to automate some tasks on github that are not accessible via the github API and which require me to be logged in and click on buttons to send AJAX requests.
Since capybara/selenium is a testing framework it helpfully creates a temporary session which has no cookies in it. I'd like to either stop it from doing that, or else I'd like to know how to load my cookie store into the browser session that it creates.
All I'm trying to do is this:
#!/usr/bin/env ruby
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
driver.navigate.to "https://github.com"
Or this:
#!/usr/bin/env ruby
require 'capybara'
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(app, :browser => :chrome)
end
session = Capybara::Session.new(:selenium)
session.visit "https://www.github.com"
In both cases I get the github.com landing page you'd see as a logged-out user or incognito mode in the browser. I'd like to get my logged-in landing page like I just fired up a web browser myself and navigated to that URL.
Since I have 2FA setup on github that makes automating the login process from the github landing page somewhat annoying, so I'd like to avoid automating logging into github. The tasks that I want to automate do not require re-authenticating via 2FA.
ANSWER:
For MacOSX+Ruby+Selenium this works:
#!/usr/bin/env ruby
require 'selenium-webdriver'
caps = Selenium::WebDriver::Remote::Capabilities.chrome("chromeOptions" => {"debuggerAddress" => "127.0.0.1:20480"}, detach: false)
driver = Selenium::WebDriver.for :chrome, :desired_capabilities => caps
driver.navigate.to "https://github.com"
Then fire up chrome with this:
% /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir=/Users/lamont/Library/Application\ Support/Google/Chrome --profile-directory=Default --remote-debugging-port=20480
Obviously the paths will need to be adjusted because they're OSX-centric and have my homedir in them.
There is also a bug in the selenium-webdriver gem for ruby where it inserts a 'detach' option which gets into a fight with 'debuggerAddress':
/Users/lamont/.rvm/gems/ruby-2.2.4/gems/selenium-webdriver-2.53.0/lib/selenium/webdriver/remote/response.rb:70:in `assert_ok': unknown error: cannot parse capability: chromeOptions (Selenium::WebDriver::Error::UnknownError)
from unknown error: unrecognized chrome option: detach
The lib/selenium/webdriver/chrome/bridge.rb file can be edited to take that out as a quick hack:
chrome_options['binary'] = Chrome.path if Chrome.path
chrome_options['nativeEvents'] = true if native_events
chrome_options['verbose'] = true if verbose
#chrome_options['detach'] = detach.nil? || !!detach
chrome_options['noWebsiteTestingDefaults'] = true if no_website_testing_defaults
chrome_options['prefs'] = prefs if prefs
To implement something similar in Ruby, check out this page that goes over that. Thanks to lamont for letting me know in the comments.
You can start chrome using a specific Chrome profile. I am not sure what the ruby implementation would look like, but in python it looks something like:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options as ChromeOptions
options = ChromeOptions()
# more on this line here later.
options.add_experimental_option('debuggerAddress', '127.0.0.1:7878')
driver = webdriver.Chrome(chrome_options=otpions)
In order for this to work you need to do a few things.
manually start chrome from terminal/command prompt with these command line arguments
--user-data-dir=/path/to/any/custom/directory/home/user/Desktop/Chromedir --profile-directory="Profile 1" --remote-debugging-port=7878
make sure "Profile 1" is already existing in the same --user-data-dir (make sure user Profile 1 has necessary chrome://components/
to run any apps that require those components)
you can use any free port in place of 7878
verify that http://localhost:7878 is running and returns value.
This should manually launch chrome with the "Profile 1" profile, and so long as it has logged into the site in question, it will stay logged in like a normal user so long as you follow these instructions to run the tests.
I used this to write a quick netflix bot that clicks the "continue playing" button when it pops up, and it's the only way to get DRM content to play as far as I have found. But it retains the cookies for the login, and also launches chrome with whatever components the profile is set up to have.
I have tried launching chrome with specific profiles before using different methodologies, but this was the only way to really force it to work how I wanted it to.
Edit: There are methods for saving cookie info as well although I don't know how well they work. Check out this link for more info, as my solution is probably not the best solution even if it works.
The show_me_the_cookies gem provides cross-driver cookie manipulation and can let you add new cookies. The one thing to be aware of when using selenium is that you need to visit the domain before you can create cookie for it, so you'll need to do something like
visit "https://www.github.com"
create_cookie(...)
visit "https://www.github.com"
for it to work - first visit just puts the browser/driver in a state where you can create the cookie, second visit actually goes to the page with the cookies set.
I had to tweak the OP's answer (from within her question) to get this going with Ruby in 2022.
Prerequisites
Chromedriver installed and allowed to run even though it's not signed:
> brew install chromedriver
> xattr -d com.apple.quarantine /usr/local/bin/chromedriver
Chrome launched and accepting commands on a specific port:
> /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir=~/Library/Application\ Support/Google/Chrome --profile-directory=Default --remote-debugging-port=20480
This created a new profile in Chrome so I signed in to my account and got the browser set up, ready to start interacting with the (legacy EdTech) site I'm trying to automate.
Actual use
require 'selenium-webdriver'
caps = Selenium::WebDriver::Remote::Capabilities.chrome("goog:chromeOptions" => {"debuggerAddress" => "127.0.0.1:20480"})
driver = Selenium::WebDriver.for :chrome, capabilities: caps
driver.navigate.to "https://www.google.com"

Why capybara codes don't work with selenium webdriver?

I am new to Capybara. I have a question about why my Capybara doesn't work when I use it together with Selenium Webdriver.
This is my sample code:
Given(/^I am on the Youtube homepage$/) do
# visit 'http://www.youtube.com'
driver = Selenium::WebDriver.for :firefox
driver.navigate.to('http://www.youtube.com')
end
When(/^I search for "([^"]*)"$/) do |search_term|
fill_in 'search_query', :with => search_term
click_on 'search-btn'
end
Then(/^videos of large rodents are returned$/) do
expect(page).to have_content 'Making Friends with a Capybara'
end
When I run it, it just open Firefox and go to Youtube homepage. But it gets error:
Capybara::ElementNotFound: Unable to find field "search_query".
Everything works with visit 'http://www.youtube.com' command.
You're creating a driver, telling it to navigate to a page and then it's going out of scope so it's getting deleted. the visit line works because it's using the current capybara driver which stays around between test steps. Rather than creating a driver manually you should be registering a driver with Capybara and then specifying which driver to use for the specific test. See drivers
Since capybara sets up a selenium driver by default for use with firefox you can just do
Capybara.default_driver = :selenium
somewhere before running your tests to make all your tests run using selenium with firefox, or since capybara registers selenium as the default javascript driver you can tag any scenarios you want to run in firefox with #javascript as shown here
#javascript
Scenario: do something something
Given ...

Failed to run custom step with the selenium cucumber ruby

I am writing a test for desktop web automation using the
selenium cucumber ruby.
My test includes both predefined and custom steps.
However, my test fails to run due to an error caused by a custom step.
The feature file that I run:
Feature: Login a customer
Scenario: Go in a call
Given I navigate to <url>
...
When I submit the form with id "custSearchSimple"
....
And I wait for 5 sec
Then element having id "accNumber" should be present
The When I submit the form with id "custSearchSimple" is a custom step.
This step is defined in the custom_step.rb. I have used the submit command of the Selenium Cucumber Ruby API. The custom_step.rb is the following file:
require 'selenium-cucumber'
# Do Not Remove This File
# Add your custom steps here
# $driver is instance of webdriver use this instance to write your custom code
#firefox browser instantiation
driver = Selenium::WebDriver.for :firefox
driver.navigate.to "https://localhost/telebet"
When(/^I submit the form with id "(.*?)"$/) do |arg1|
element= driver.submit(:id,"#{arg1}")
end
When I run the feature file by running cucumber features/name_of_the_file.feature, I get the NoMethodError error:
When I submit the form with id "custSearchSimple" # features/step_definitions/custom_steps.rb:12
private method `submit' called for #<Selenium::WebDriver::Driver:0x94c4bde4bdff4d6 browser=:firefox> (NoMethodError)
I could not find any example using the Selenium Cucumber Ruby API for writing custom steps. I suspect that I might have omitted some commands for the selenium web driver ruby. Something is missing that I could not find. Does anyone know why I get this error?
Maybe I am confused here but:
When(/^I submit the form with id "(.*?)"$/) do |arg1|
submit_form arg1
end
def submit_form(form_id)
submit("id", form_id)
end
Would do what you want? submit_form isn't a cucumber step, it's a ruby method - probably why you're getting Cucumber::UndefinedDynamicStep.

Unsupported command-line flag: --ignore-certificate-errors (in Ruby)

Using Ruby 2.0.0 p481 in RubyMine and chromedriver 2.10
When Chrome starts it displays a message in a yellow popup bar: "You are using an unsupported command-line flag: --ignore-certificate-errors. Stability and security will suffer." This simple example reproduces the problem.
require "selenium-webdriver"
driver = Selenium::WebDriver.for :chrome
driver.navigate.to login_url
This question has been answered for Java and Python. I have looked everywhere for a Ruby analog. Does anyone have a suggestion or know how to translate the Python answer (Unsupported command-line flag: --ignore-certificate-errors) to Ruby? Thank you!
The Ruby selenium-webdriver API doesn't expose a separate Chrome options object like Java/Python but you can set the options via "Capabilities".
The Capabilities web page provides a Ruby example and the table of recognized capabilities that you can inject. Plugging those together with excludeSwitches:
caps = Selenium::WebDriver::Remote::Capabilities.chrome("chromeOptions" => {"excludeSwitches" => [ "--ignore-certificate-errors" ]})
driver = Selenium::WebDriver.for :chrome, desired_capabilities: caps
Take a look at Watir too, it's a front end for WebDriver.
Their examples show how you can send a :switches array which is passed straight through to the web driver so you can do the same. That makes adding other switches a bit easier rather than going through capabilities.
There is a chromedriver issue on the topic as well. There are posts detailing that you can add a --test-type argument to work around the certificate issue and ruby code examples like above.
I adjusted:
driver = Selenium::WebDriver.for :chrome
to read:
driver = Selenium::WebDriver.for :chrome, :switches => %w[--test-type]
...and the script ran successfully without the yellow flag. Clearly, other command-line switches could be added.
Thank you to Nguyen Vu Hoang and mtm.
I donot know ruby, however my approach is set mode "test-type" to ChromeDriver capabilities
Here's my sample code in Java
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities = DesiredCapabilities.chrome();
ChromeOptions options = new ChromeOptions();
options.addArguments("test-type", "start-maximized",
"no-default-browser-check");
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
With Capybara:
Capybara.register_driver :chrome do |app|
Capybara::Selenium::Driver.new(app, browser: :chrome, switches: ['--test-type'])
end
This error caused my rspec tests to fail. I think it was causing Chrome to slow down so the above fixes did remove the error messages but did not resolve my problem of my tests failing.
If you are using chromedriver-helper then this should fix the problem. Run this from the command line
chromedriver-update
This is described more in chromedriver-helper, "This might be necessary on platforms on which Chrome auto-updates, which has been known to introduce incompatibilities with older versions of chromedrive"
Once I ran this I was able to remove the fixes described elsewhere and Chrome ran with out warnings.

Selenium can't find fields with type number

I'm having a problem getting Cucumber to find fields with the HTML5 type="number". I'm not a big fan of the way they look in the browser, but I have a few fields that need the number keyboard on mobile, and this seems to be the easiest way to get it. I'm using SimpleForm to build forms and when I set :as => :text everything works, but if I set :as => :number, the fields don't get filled out. I don't get any error, the field just doesn't get filled.
To be specific, when I have a step like this:
And I fill in "application_form_age" with "52"
then this tag won't get filled in:
<input class=​"numeric integer required" id=​"application_form_age" min=​"0" name=​"application_form[age]​" size=​"50" step=​"1" type=​"number">​
but this one works:
<input class=​"string required" id=​"application_form_age" name=​"application_form[age]​" size=​"50" type=​"text">​
Also, it only happens in #javascript scenarios. In situations where #javascript isn't necessary and the scenario doesn't launch a browser, that works fine too.
Versions of things:
capybara (2.2.1)
cucumber (1.3.14)
selenium-webdriver (2.41.0)
simple_form (2.1.1)
webrat (0.7.3)
Firefox 29.0
I'm stumped. I tried yanking out a bunch of my application JS and CSS to see if something I'm doing is breaking it, but no luck with that. I'm just patching it out by forcing those fields not to have HTML5 type number in my test environment, but I don't want to live like that. Is anyone else seeing this? I haven't been able to find any references to it, which makes it seem like it's something I'm doing. But I haven't been able to figure it out.
Ok, I have found firefox has an option to disable number input field support: 'dom.forms.number'.
So if you add the following lines in your env.rb, number input gets disabled and tests work again.
Capybara.register_driver :selenium do |app|
profile = Selenium::WebDriver::Firefox::Profile.new
profile["dom.forms.number"] = false
Capybara::Selenium::Driver.new(app, :browser => :firefox, :profile => profile)
end
First off, I think you have some confusion regarding those frameworks. Cucumber is a BDD framework, which doesn't automate browsers in any way, so this question has nothing to do with it (This is why I removed it from your question title).
Looks like you are using Capybara, which is an ATDD framework. You might probably consider showing us the Capybara code you use in order diagnose your problem.
Under the hood, I assume you use Selenium WebDriver, I can confirm that Selenium works fine with <input type="number"> (Tested with Firefox 28, which is the one selenium-webdriver (2.41.0) supports to).
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :firefox
DEMO_PAGE = <<-eos
data:text/html,
<input class=​"numeric integer required" id=​"application_form_age" min=​"0" name=​"application_form[age]​" size=​"50" step=​"1" type=​"number">
eos
driver.get(DEMO_PAGE)
driver.find_element(:tag_name, 'input').send_keys('25')
So you might want to create a similar demo using Capybara to test this functionality.
If the demo works, then we need take a closer look at your application.
Othwewise, please raise a ticket for Capybara developers.

Resources