Selenium driver for remote browser - ruby

I am using selenium-webdriver and running this test on a remote machine.
I want to redirect the user to the mobile website by changing the user agent.
I tried with the following, but it doesn't work.
require 'selenium-webdriver'
capabilities = Selenium::WebDriver::Remote::Capabilities.firefox(:firefox_profile => 'Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10')
browser = Selenium::WebDriver.for :remote, :desired_capabilities => capabilities
browser.get "http://mobile.website.com/"
I am getting this error on my browser
Selenium::WebDriver::Error::WebDriverError (Could not find Firefox binary (os=linux). Make sure Firefox is installed or set the path manually with Selenium::WebDriver::Firefox::Binary.path=):
a. Is there any way to achieve this without using selenium?
b. Is there any way to detect the user's browser and redirect the user to URL with the mobile user agent string(iphone,android)?

Why not test your website in a real mobile device, e.g. using Appium.
You can use Appium to drive the browser in your mobile.

Related

Accessing web-cam using Cypress

I am trying to automate a web-app (company specific) using Cypress which contains a page to take a picture using a web-cam. On clicking the 'Take a Photo' button, it shows an error message asking to provide access to the camera.
But, a browser pop-up is not displayed asking for permissions unlike the open-source website - https://webcamtests.com/
On looking at Cypress documentation, a default set of Chrome switches are being added to the browser before the launch which also includes
'--use-fake-device-for-media-stream'
'--use-fake-ui-for-media-stream'
I've removed them using the below code that is placed in the config file .
launchOptions.args = launchOptions.args.filter((arg) => {
return arg !== '--use-fake-device-for-media-stream' && arg !== '--use-fake-ui-for-media-stream'
})
Also, in the documentation it specifically says this reg the default switches- https://docs.cypress.io/guides/guides/launching-browsers#Launching-Browsers
"Disables prompts requesting permission to use devices like cameras or mics"
Am looking to see what is the corresponding switch for this and is there a way to enable the prompt to provide access?
Any help/suggestion is appreciated.
Cypress Version: 12.5.1
Chrome Version: 109
Platform - Mac
Note:
I've also tried using an open source library for enabling the camera permissions but it did not work.
https://github.com/kamranayub/cypress-browser-permissions
The prompt is displayed when automated using Web-Driver.
Please try this:
cy.request({
method: 'GET',
url: 'https://webcamtests.com/',
headers: {
'Content-Type': 'text/html',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'
},
followRedirect: false,
body: {}
});
Above test simulate a real user request to the target website and trigger camera permissions pop-up.
Please keep in mind, it might not work for all websites as the pop-up is controlled by the website and user's browser.

Set log level for chrome logs in ruby

I'm trying to assert that there is no mixed content in a website. I have set the log level equal to 1 in the chrome switches , but i m still unable to retrieve warning messages from the browser, here is the code im using.
browser = Watir::Browser.new :chrome,
switches: %w[--disable-gpu --no-sandbox
--disable-prompt-on-repost
--windows-size=3200x1800
--log-level=1]
console_log = browser.driver.manage.logs.get (:browser)
What am i doing wrong? or there is other way to set this log level to capture errors and warnings?
Work done ,, just changing the way i was passing the settings to the browsr is working
options = Selenium::WebDriver::Chrome::Options.new
options.add_argument('--disable-infobars')
options.add_argument('--disable-gpu')
options.add_argument('--no-sandbox')
options.add_argument('--disable-prompt-on-repost')
options.add_argument('--user-agent="Mozilla/5.0 (Linux; Android 6.0.1; SAMSUNG SM-G925F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.0 Chrome/44.0.2403.133 Mobile Safari/537.36"')

Automate Chrome Extensions With Selenium and Ruby

I am currently working on an automation project where I need to use Ruby/Selenium to discover specific http headers returned to the user after authentication to a web app. I am able to automate the web app just fine; however, when I try to use a Chrome extension the browser returns the following error:
The webpage at chrome-extension://[extension address] might be temporarily down or it may have moved permanently to a new web address.
After looking into this, it appears that the Selenium web driver is using a different Chrome profile than my regular Chrome profile. As such, I was wondering if someone knew if there is a way to to tell Selenium to use my regular Chrome profile with the extension loaded or build a new profile and install the extension during runtime.
So far, most of the answers I have found were centralized around Python and Java. Please let me know if I can provide more information.
To launch Chrome with the default profile on Windows:
require 'selenium-webdriver'
switches = ['user-data-dir='+ENV['LOCALAPPDATA']+'\\Google\\Chrome\\User Data']
driver = Selenium::WebDriver.for :chrome, :switches => switches
driver.navigate.to "https://www.google.co.uk"
Or to add an extension to the created profile:
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome,
:desired_capabilities => Selenium::WebDriver::Remote::Capabilities.chrome({
'chromeOptions' => {
'extensions' => [
Base64.strict_encode64(File.open('C:\\App\\extension.crx', 'rb').read)
]
}
})
driver.navigate.to "https://www.google.co.uk"

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"

RubyMine - NoMethodError: Undefined method 'get' for nil:nilClass - Webdriver UserAgent

I am new to RubyMine and trying to debug an project that I did not write myself.
The error when I ran the Project.feature and it stopped at the first line 'Given I go to this Website'.
"NoMethodError: Undefined method 'get' for nil:nilClass" in filepath/Common_steps_json.rb:14 in '/^I go to this website$'
Going to the link provided, it directed me to my Common_steps_json.rb file where the code written was
Given /^I go to this website$/ do
#driver.get 'https://www.somewebsite.com/field1/field2/'
sleep 3
end
I believe this is the correct format to navigate to a URL using Selenium-Webdriver. So this prompted me to check the environment file env.rb to see how the driver was called. There I found this.
require "selenium-webdriver"
require "webdriver-user-agent"
.
.
.
Before('#driver_iphone_portrait') do
#driver = UserAgent.driver(:browser => :firefox, :agent => :iphone, :orientation => :portrait)
#base_url = 'https://www.somewebsite.com/'
#driver.manage.timeouts.implicit_wait = 2
#verification_errors = []
end
I checked this link to make sure that the selenium webdriver user agent was called correctly but I am not so sure that it is. I used Interactive Ruby to see if I could call the driver using the UserAgent.Driver format but it ran into a error
NameError: uninitialized constant UserAgent
If anyone has any advice on how to properly format UserAgent for RubyMine, I would really appreciate it. Thanks!
It looks like your code is trying to run some tests using Firefox with a profile that uses a user agent property to emulate the iPhone.
Unfortunately, your code is using a depreciated gem written by Alister Scott. You will be unable to continue to use this gem, and should look for a work around.
UPDATE Alister Scott just announced that the maintenance of the gem has been taken over by Jeff "Cheezy" Morgan and is available on the Github repo.
In fact, it looks like this was a pretty simple and standard gem wrapper that you can employ without all the sugary wrapper goodness. Actually, you can easily configure this setting in your WebDriver Profile setup
Try something like this to replace the UserAgent string (and take out the require 'webdriver-user-agent' line too):
profile = Selenium::WebDriver::Firefox::Profile.new
profile["general.useragent.override"] = "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3"
#driver = Selenium::WebDriver.for :firefox, :profile => profile
That should create the #driver object and allow you to use the get method to open the website with the Firefox browser. The browser should be sending in the headers of the requests the user agent you specified in the code, and your web pages should be rendering as they would if an iPhone was browsing.

Resources