Using selenium-webdriver and capybara in rspec, in a features spec I'm trying to get the HTTP response of a plain text request, namely /robots.txt
But instead of getting the plain text response, I get the text response wrapped in HTML:
expected: "User-agent: *\nDisallow:\n\nSitemap: https://prj.org/sitemap.xml\n"
got: "<html><head><link rel=\"alternate stylesheet\" type=\"text/css\" href=\"resource://content-accessible/plaintext.css\" title=\"Wrap Long Lines\"></head><body><pre>User-agent: *\nDisallow:\n\nSitemap: https://prj.org/sitemap.xml\n</pre></body></html>"
When fetching /robots.txt with curl I get the expected plain text response. So I've been through Firefox options, and I found out I needed to disable plain_text.wrap_long_lines option.
And I cannot succeed to pass the option to geckodriver.
I first tried to pass it to the Options object, like this:
Capybara.register_driver :firefox_headless do |app|
options = ::Selenium::WebDriver::Firefox::Options.new
options.headless!
options.add_preference 'plain_text.wrap_long_lines', false
Capybara::Selenium::Driver.new app, browser: :firefox, options: options
end
Then I tried to pass it to a Profile object.
Capybara.register_driver :firefox_headless do |app|
options = ::Selenium::WebDriver::Firefox::Options.new
options.headless!
profile = Selenium::WebDriver::Firefox::Profile.new
profile['plain_text.wrap_long_lines'] = false
Capybara::Selenium::Driver.new app, browser: :firefox, options: options, profile: profile
end
In both cases, the result is the same. Any idea as per why? Thanks!
Using:
selenium-webdriver 3.14.1
capybara 3.7.2
geckodriver 0.22.0
The issue you're seeing here is that when Firefox opens a text file it automatically wraps it in some boilerplate html in order for the browser to be able to display it. You don't show your test code you're using - but whatever you're doing should boil down to something like
# If using minitest
visit('/robots.txt')
find('body > pre').assert_text("User-agent: *\nDisallow:\n\nSitemap: https://prj.org/sitemap.xml\n", exact: true)
# If using RSpec
visit('/robots.txt')
expect(find('body > pr')).to have_text("User-agent: *\nDisallow:\n\nSitemap: https://prj.org/sitemap.xml\n", exact: true)
Related
I am using selenoid for remote browser testing in ruby.
In that I am using 'selenium-webdriver', 'capybara', 'rspec' for automation. And I am using attach_file method for uploading file to browser
I want to upload file on Firefox and Chrome browser but it raises error on both;
In chrome
Selenium::WebDriver::Error::UnknownCommandError: unknown command: unknown command: session/***8d32e045e3***/se/file
In firefox
unexpected token at 'HTTP method not allowed'
So After searching I found the solution for chrome which is to set w3c option false in caps['goog:chromeOptions'] > caps['goog:chromeOptions'] = {w3c: false}
So now chrome is using OSS bridge for handshaking but I don't know how to do it in Firefox. Similar solution is not available for Firefox.
My browser capabilities are following:
if ENV['BROWSER'] == 'firefox'
caps = Selenium::WebDriver::Remote::Capabilities.new
caps['browserName'] = 'firefox'
# caps['moz:firefoxOptions'] = {w3c: false} ## It is not working
else
caps = Selenium::WebDriver::Remote::Capabilities.new
caps["browserName"] = "chrome"
caps["version"] = "81.0"
caps['goog:chromeOptions'] = {w3c: false}
end
caps["enableVNC"] = true
caps["screenResolution"] = "1280x800"
caps['sessionTimeout'] = '15m'
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(app, browser: :remote,
:desired_capabilities => caps,
:url => ENV["REMOTE_URL"] || "http://*.*.*.*:4444/wd/hub"
)
end
Capybara.configure do |config|
config.default_driver = :selenium
end
I have found the problem. There is bug in selenium server which run on java so I have to change my selenium-webdriver gem version 3.142.7 and monkey-patch.
You can find more information here about the bug and resolution.
For now I have to change my gem and monkey patch the selenium-webdriver-3.142.7\lib\selenium\webdriver\remote\w3c\commands.rb file. check for below line which is on line no 150.
upload_file: [:post, 'session/:session_id/se/file']
and update it to
upload_file: [:post, 'session/:session_id/file']
i had a similar issue with rails 7. the issue is connected with the w3c standard. the core problem is that the webdriver for chrome uses a non-w3c standard url for handling file uploads. when uploading a file, the webdriver uses the /se/file url path to upload. this path is only supported by the selenium server. subsequently, the docker image provided by selenium works fine. yet, if we use chromedriver, the upload fails. more info.
we can solve this, by forcing the webdriver to use the standard-compliant url by overriding the :upload_file key in Selenium::WebDriver::Remote::Bridge::COMMANDS. since, the initialization of this the COMMANDS constant does not happen when the module is loaded, we can override the attach_file method to make sure the constant is set correctly. here the hacky code:
module Capybara::Node::Actions
alias_method :original_attach_file, :attach_file
def attach_file(*args, **kwargs)
implement_hacky_fix_for_file_uploads_with_chromedriver
original_attach_file(*args, **kwargs)
end
def implement_hacky_fix_for_file_uploads_with_chromedriver
return if #hacky_fix_implemented
original_verbose, $VERBOSE = $VERBOSE, nil # ignore warnings
cmds = Selenium::WebDriver::Remote::Bridge::COMMANDS.dup
cmds[:upload_file] = [:post, "session/:session_id/file"]
Selenium::WebDriver::Remote::Bridge.const_set(:COMMANDS, cmds)
$VERBOSE = original_verbose
#hacky_fix_implemented = true
end
end
In Firefox images we support /session/<id>/file API by adding Selenoid binary which emulates this API instead of Geckodriver (which does not implement it).
Based off the answer here I am trying to get Chrome to run headless in my script.
The snippet of code below is inside of a function called login() that logs into our ERP system:
if headless == True:
options = Options()
options.headless = True
#Load webdriver
driver = webdriver.Chrome(options=options, executable_path=r'C:/Users/d.kelly/Desktop/Python/chromedriver_win32/chromedriver.exe')
if headless == False:
driver = webdriver.Chrome('C:/Users/d.kelly/Desktop/Python/chromedriver_win32/chromedriver.exe')
window_before_login = driver.window_handles[0]
### Removed Code Block that fills out login form and clicks 'Login' button ###
# Switch to new window ERP (PLEX) launches and close original blank one no longer needed.
window_before_login = driver.window_handles[0]
window_title = driver.title
driver.switch_to.window(window_before_login)
driver.close()
driver.switch_to.window(driver.window_handles[0])
When I call my function like so:
login(headless=False)
It throws no errors and my entire script executes just fine.
When I call my function like this:
def login(headless=True)
I get the following errors:
DevTools listening on ws://127.0.0.1:57567/devtools/browser/69f9e357-dccf-4e38-8d6b-78030462379a
[0204/072436.206:INFO:CONSOLE(6)] "Error parsing a meta element's content: ';' is not a valid key-value pair separator. Please use ',' instead.", source: https://test.plexonline.com/modules/systemadministration/login/index.aspx? (6)
[0204/072437.699:INFO:CONSOLE(6)] "Error parsing a meta element's content: ';' is not a valid key-value pair separator. Please use ',' instead.", source: https://test.plexonline.com/Modules/SystemAdministration/Login/Index.aspx (6)
[0204/072437.722:INFO:CONSOLE(1)] "Scripts may close only the windows that were opened by it.", source: (1)
[0204/072441.162:INFO:CONSOLE(751)] "Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.", source: https://test.plexonline.com/Modules/scripts/ajax.js (751)
I am using Chrome Version 79.0.3945.130 (Official Build) (64-bit), Selenium 3.141.0, and Python 3.7.4.
Any ideas what I am doing wrong? Thank you!
I'm using a ruby/cucumber/capybara framework with versions:
capybara (2.10.1)
selenium-webdriver (3.0.0)
ruby 2.3.1p112 (2016-04-26 revision 54768) [x64-mingw32]
and I'm trying to register a new driver with some settings passed in the profile to capybara. My code looks like this:
Capybara.register_driver :debug do |app|
profile = Selenium::WebDriver::Firefox::Profile.new
Capybara::Selenium::Driver.new(app, :browser => :firefox, :profile => profile)
end
and I've tried as well with:
Capybara::Selenium::Driver.new(app, :profile => profile)
Then I just use the following to select that driver:
Capybara.default_driver = :debug
but in both cases, when I try to run any test, I get the following error:
ArgumentError: unknown option: {:profile=>#<Selenium::WebDriver::Firefox::Profile:0x000000068ca798 #model=nil, #native_events=true, #secure_ssl=false, #untrusted_issuer=true, #load_no_focus_lib=false, #additional_prefs={}, #extensions={}>}
Any idea what the problem could be? and how to ammend it?
Firefox Profiles are not yet supported in Ruby bindings for geckodriver, which is needed for Firefox 48+. Watch this issue for (hopefully very soon) resolution: https://github.com/SeleniumHQ/selenium/issues/2933
I have an angularJs app that sends a base64 encoded image (or file) to my rails4 server api that uses paperclip to store attachments. Everything works fine until the content_type_validation paperclip does.
For some reason, paperclip determines the content-type's been spoofed and get the following error message:
[paperclip] Content Type Spoof: Filename 1413325092.jpg (["image/jpeg"]), content type discovered from file command: application/octet-stream; charset=binary. See documentation to allow this combination.
I create the paperclip attachment with the following code:
def self.create_from_base64(base64_string)
decoded_data = Base64.decode64(base64_string)
# create 'file' understandable by Paperclip
data = StringIO.new(decoded_data)
data.class_eval do
attr_accessor :content_type, :original_filename
end
# set file properties
data.content_type = 'application/octet-stream'
data.original_filename = "#{Time.now.to_i}.jpg"
end
I've tried different things but for some reason even when I set data.content_type = 'application/octet-stream', the error is exactly the same, and paperclip it's been spoofed.
Any ideas?
Thanks,
EDIT:
I have the following validation:
validates_attachment_content_type :file, :content_type => [/png\Z/, /jpe?g\Z/, /application\/octet-stream*/]
I am using tcpdf with Cakephp. The PDFs are downloaded good in Linux but when it comes to Mac for Opera and Safari it add .html ectension to it.
I also noticed that even if it downloads as PDF document in FireFox and Google Chrome, the Pop-up to save as reads it as "HTML document" but save as PDF. PLease help me with this.
Try to modify headers, like:
header("Content-Description: File Transfer");
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file_name));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Cache-Control: private", false); // required for certain browsers
header('Pragma: public');
header('Content-Length: ' . filesize($file_name));
Hope it works. :)
It seems like Mac and Safari are more strict when it comes to mime types, and always obeys the content type set in your scripts. So if the Content type is being set to text/html, Safari will expect it to be a HTML document and add the html extension. Firefox and Chrome are using this content-type header to present the file type (HTML document), but does not change the filename so it saves as a PDF.
As you are using CakePHP, it's a good idea to use the built in file response in your Controller:
$this->response->file($path,array('download' => true, 'name' => $filename));
return $this->response;
This will correctly set the headers you need for most files. See here for docs: http://book.cakephp.org/2.0/en/controllers/request-response.html#sending-files
Be warned, CakePHP might not know the mimetype of some files, and will default to text/html. Then you'll get the same problem in Safari. It's a good idea to test and if you see this happening, set the mime types yourself (BEFORE setting the file):
$ext = pathinfo($filename, PATHINFO_EXTENSION);
switch ($ext) {
case 'dotx':
$this->response->type('application/vnd.openxmlformats-officedocument.wordprocessingml.template');
break;
}
$this->response->file($path,array('download' => true, 'name' => $filename));
return $this->response;
I found by adding
$this->response->type('application/pdf');
to the view file and by updating to the latest version of the TCPDF vendor files it resolved the same issue for us (as well as other display issues).
In your controller simply add this
$this->response->header(array('Content-type: application/pdf'));
$this->response->type('pdf');
By adding this same issue is solved to me.