teamcapybara--capybara/lib/capybara/spec/test_app.rb

306 lines
6.7 KiB
Ruby
Raw Normal View History

2016-03-08 00:52:19 +00:00
# frozen_string_literal: true
2018-03-01 00:11:41 +00:00
require 'sinatra/base'
2015-05-20 20:08:24 +00:00
require 'tilt/erb'
require 'rack'
2009-12-19 10:52:08 +00:00
require 'yaml'
2009-11-04 22:32:35 +00:00
class TestApp < Sinatra::Base
2019-02-24 23:32:07 +00:00
class TestAppError < Exception; end # rubocop:disable Lint/InheritException
2020-11-26 20:16:11 +00:00
2019-02-24 23:32:07 +00:00
class TestAppOtherError < Exception # rubocop:disable Lint/InheritException
def initialize(string1, msg)
2020-09-05 19:24:43 +00:00
super()
@something = string1
@message = msg
end
end
2009-11-05 16:35:45 +00:00
set :root, File.dirname(__FILE__)
set :static, true
set :raise_errors, true
set :show_exceptions, false
2009-11-04 22:32:35 +00:00
# Also check lib/capybara/spec/views/*.erb for pages not listed here
2009-11-04 22:32:35 +00:00
get '/' do
2018-03-01 00:11:41 +00:00
response.set_cookie('capybara', value: 'root cookie', domain: request.host, path: request.path)
'Hello world! <a href="with_html">Relative</a>'
2009-11-04 22:32:35 +00:00
end
get '/foo' do
'Another World'
end
2009-11-12 17:58:27 +00:00
get '/redirect' do
redirect '/redirect_again'
end
get '/redirect_with_fragment' do
redirect '/landed#with_fragment'
end
2009-11-12 17:58:27 +00:00
get '/redirect_again' do
redirect '/landed'
end
post '/redirect_307' do
redirect '/landed', 307
end
2018-06-08 17:10:26 +00:00
post '/redirect_308' do
redirect '/landed', 308
end
get '/referer_base' do
2018-03-01 00:11:41 +00:00
'<a href="/get_referer">direct link</a>' \
2021-07-25 02:53:46 +00:00
'<a href="/redirect_to_get_referer">link via redirect</a>' \
'<form action="/get_referer" method="get"><input type="submit"></form>'
end
get '/redirect_to_get_referer' do
redirect '/get_referer'
end
get '/get_referer' do
2018-07-10 21:18:39 +00:00
request.referer.nil? ? 'No referer' : "Got referer: #{request.referer}"
end
get '/host' do
"Current host is #{request.scheme}://#{request.host}:#{request.port}"
end
get '/redirect/:times/times' do
times = params[:times].to_i
if times.zero?
2018-07-10 21:18:39 +00:00
'redirection complete'
else
redirect "/redirect/#{times - 1}/times"
end
end
2009-11-12 17:58:27 +00:00
get '/landed' do
2018-07-10 21:18:39 +00:00
'You landed'
2009-11-12 17:58:27 +00:00
end
post '/landed' do
"You post landed: #{params.dig(:form, 'data')}"
end
get '/with-quotes' do
2018-03-01 00:11:41 +00:00
%q("No," he said, "you can't do that.")
end
2009-11-24 20:32:25 +00:00
get '/form/get' do
2020-09-05 19:24:43 +00:00
%(<pre id="results">#{params[:form].to_yaml}</pre>)
2009-11-08 00:13:16 +00:00
end
post '/relative' do
2020-09-05 19:24:43 +00:00
%(<pre id="results">#{params[:form].to_yaml}</pre>)
end
2009-11-24 20:32:25 +00:00
get '/favicon.ico' do
nil
end
post '/redirect' do
redirect '/redirect_again'
end
2018-07-10 21:18:39 +00:00
delete '/delete' do
'The requested object was deleted'
end
2018-07-10 21:18:39 +00:00
get '/delete' do
'Not deleted'
end
2010-02-12 13:41:41 +00:00
get '/redirect_back' do
redirect back
end
2011-07-18 19:08:55 +00:00
get '/redirect_secure' do
redirect "https://#{request.host}:#{request.port}/host"
2011-07-18 19:08:55 +00:00
end
get '/slow_response' do
sleep 2
'Finally!'
end
get '/set_cookie' do
cookie_value = 'test_cookie'
response.set_cookie('capybara', cookie_value)
"Cookie set to #{cookie_value}"
end
get '/get_cookie' do
request.cookies['capybara']
end
get '/get_header' do
env['HTTP_FOO']
end
get '/get_header_via_redirect' do
redirect '/get_header'
end
get '/error' do
2018-07-10 21:18:39 +00:00
raise TestAppError, 'some error'
end
get '/other_error' do
2018-07-10 21:18:39 +00:00
raise TestAppOtherError.new('something', 'other error')
end
get '/load_error' do
raise LoadError
end
2015-04-14 19:46:00 +00:00
get '/with.*html' do
erb :with_html, locals: { referrer: request.referrer }
2015-04-14 19:46:00 +00:00
end
get '/with_title' do
<<-HTML
Switch test file to standards mode Goal ==== Many of the test files were not specifying a doctype. This means they are operating in quirks mode which behaves differently than standards mode. Most systems in production use today operate in some sort of standards mode (most often HTML5). There is a question on what modes Capybara should support. There is quirks mode (no doctype), HTML4, HTML5, various XHTML formats (strict, traditional, frameset). My suggestion is that we don't care about quirks mode as it is a legacy format. If someone is using that they will need to live with those consequences. For the other formats I'm going to assume if it works in HTML5 it will work in the others. When that assumption is shown to be false a bug can be filed and we can create a specific test to cover that format for that scenario but I think running basically every test in every doctype would add more complication to the test suite than it is worth. Implementation ============== In general the idea is just to add the following to all the test HTML: <!DOCTYPE html> This declares it a standardized HTML5 document following standards mode rather than quirks mode. Many of the templates not only lack a doctype but also lack other HTML structure to be a valid HTML file (i.e. not html tag, head tag, body tag, etc). Basically they are without a layout. I assume this is because the test does not dependent a valid HTML file. But since we want to run in standards mode I think we should add a layout to these files. Rather than add boilerplate layout code to every file I'm instead using the layout feature of Sinatra. If the template file already has a doctype then just render it without the standard layout. Otherwise render it with the standard layout. There were a few files that indicated a XHTML namespace. Since we are doing all HTML5 doctypes we do not need a XHTML namespace and therefore those attributes were removed. I suspect these namespaces attriubtes were just copy/paste boilerplate. The exception to this is the `with_namespace.erb` template. This seems to be testing something related to XHTML namespaces so I left it and instead added a XHTML Strict doctype. The `with_title` template I don't think is used since there is an inline HTML doc on the Sinatra code with the same endpoint. I suspect that is leftover from an old refactor so removed that file completely. Test Failures ------------- With these changes made we ended up with test failures related to scroll (expected as that is what prompted this work) and frames. I will follow up with additional commits to correct these failures. They are currently: rspec './lib/capybara/spec/spec_helper.rb[1:44:3]' # Capybara::Session selenium_chrome #frame_title should return the title in the main frame rspec './lib/capybara/spec/spec_helper.rb[1:44:1]' # Capybara::Session selenium_chrome #frame_title should return the title in a frame rspec './lib/capybara/spec/spec_helper.rb[1:44:2]' # Capybara::Session selenium_chrome #frame_title should return the title in FrameTwo rspec './lib/capybara/spec/spec_helper.rb[1:98:5]' # Capybara::Session selenium_chrome #scroll_to can scroll the window to the vertical bottom rspec './lib/capybara/spec/spec_helper.rb[1:98:3]' # Capybara::Session selenium_chrome #scroll_to can scroll an element to the center of the viewport rspec './lib/capybara/spec/spec_helper.rb[1:98:2]' # Capybara::Session selenium_chrome #scroll_to can scroll an element to the bottom of the viewport rspec './lib/capybara/spec/spec_helper.rb[1:98:6]' # Capybara::Session selenium_chrome #scroll_to can scroll the window to the vertical center rspec './lib/capybara/spec/spec_helper.rb[1:98:7]' # Capybara::Session selenium_chrome #scroll_to can scroll the window to specific location rspec './lib/capybara/spec/spec_helper.rb[1:98:15]' # Capybara::Session selenium_chrome #scroll_to can scroll the window by a specific amount
2021-07-22 16:23:20 +00:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>#{params[:title] || 'Test Title'}</title>
</head>
<body>
<svg><title>abcdefg</title></svg>
</body>
</html>
HTML
end
2022-06-08 11:12:57 +00:00
get '/with_iframe' do
<<-HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>Test with Iframe</title>
</head>
<body>
<iframe src="#{params[:url]}" id="#{params[:id]}"></iframe>
</body>
</html>
HTML
end
get '/base/with_base' do
<<-HTML
<!DOCTYPE html>
<html>
<head>
<base href="/">
<title>Origin</title>
</head>
<body>
<a href="with_title">Title page</a>
<a href="?a=3">Bare query</a>
</body>
</html>
HTML
end
get '/base/with_other_base' do
<<-HTML
<!DOCTYPE html>
<html>
<head>
<base href="/base/">
<title>Origin</title>
</head>
<body>
<a href="with_title">Title page</a>
<a href="?a=3">Bare query</a>
</body>
</html>
HTML
end
get '/csp' do
response.headers['Content-Security-Policy'] = "default-src 'none'; connect-src 'self'; base-uri 'none'; font-src 'self'; img-src 'self' data:; object-src 'none'; script-src 'self' 'nonce-jAviMuMisoTisVXjgLoWdA=='; style-src 'self' 'nonce-jAviMuMisoTisVXjgLoWdA=='; form-action 'self';"
<<-HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>CSP</title>
</head>
<body>
<div>CSP</div>
</body>
</html>
HTML
end
2018-06-17 17:29:46 +00:00
get '/download.csv' do
2018-07-10 21:18:39 +00:00
content_type 'text/csv'
2018-06-17 17:29:46 +00:00
'This, is, comma, separated' \
2021-07-25 02:53:46 +00:00
'Thomas, Walpole, was , here'
2018-06-17 17:29:46 +00:00
end
2010-02-12 13:41:41 +00:00
get '/:view' do |view|
Switch test file to standards mode Goal ==== Many of the test files were not specifying a doctype. This means they are operating in quirks mode which behaves differently than standards mode. Most systems in production use today operate in some sort of standards mode (most often HTML5). There is a question on what modes Capybara should support. There is quirks mode (no doctype), HTML4, HTML5, various XHTML formats (strict, traditional, frameset). My suggestion is that we don't care about quirks mode as it is a legacy format. If someone is using that they will need to live with those consequences. For the other formats I'm going to assume if it works in HTML5 it will work in the others. When that assumption is shown to be false a bug can be filed and we can create a specific test to cover that format for that scenario but I think running basically every test in every doctype would add more complication to the test suite than it is worth. Implementation ============== In general the idea is just to add the following to all the test HTML: <!DOCTYPE html> This declares it a standardized HTML5 document following standards mode rather than quirks mode. Many of the templates not only lack a doctype but also lack other HTML structure to be a valid HTML file (i.e. not html tag, head tag, body tag, etc). Basically they are without a layout. I assume this is because the test does not dependent a valid HTML file. But since we want to run in standards mode I think we should add a layout to these files. Rather than add boilerplate layout code to every file I'm instead using the layout feature of Sinatra. If the template file already has a doctype then just render it without the standard layout. Otherwise render it with the standard layout. There were a few files that indicated a XHTML namespace. Since we are doing all HTML5 doctypes we do not need a XHTML namespace and therefore those attributes were removed. I suspect these namespaces attriubtes were just copy/paste boilerplate. The exception to this is the `with_namespace.erb` template. This seems to be testing something related to XHTML namespaces so I left it and instead added a XHTML Strict doctype. The `with_title` template I don't think is used since there is an inline HTML doc on the Sinatra code with the same endpoint. I suspect that is leftover from an old refactor so removed that file completely. Test Failures ------------- With these changes made we ended up with test failures related to scroll (expected as that is what prompted this work) and frames. I will follow up with additional commits to correct these failures. They are currently: rspec './lib/capybara/spec/spec_helper.rb[1:44:3]' # Capybara::Session selenium_chrome #frame_title should return the title in the main frame rspec './lib/capybara/spec/spec_helper.rb[1:44:1]' # Capybara::Session selenium_chrome #frame_title should return the title in a frame rspec './lib/capybara/spec/spec_helper.rb[1:44:2]' # Capybara::Session selenium_chrome #frame_title should return the title in FrameTwo rspec './lib/capybara/spec/spec_helper.rb[1:98:5]' # Capybara::Session selenium_chrome #scroll_to can scroll the window to the vertical bottom rspec './lib/capybara/spec/spec_helper.rb[1:98:3]' # Capybara::Session selenium_chrome #scroll_to can scroll an element to the center of the viewport rspec './lib/capybara/spec/spec_helper.rb[1:98:2]' # Capybara::Session selenium_chrome #scroll_to can scroll an element to the bottom of the viewport rspec './lib/capybara/spec/spec_helper.rb[1:98:6]' # Capybara::Session selenium_chrome #scroll_to can scroll the window to the vertical center rspec './lib/capybara/spec/spec_helper.rb[1:98:7]' # Capybara::Session selenium_chrome #scroll_to can scroll the window to specific location rspec './lib/capybara/spec/spec_helper.rb[1:98:15]' # Capybara::Session selenium_chrome #scroll_to can scroll the window by a specific amount
2021-07-22 16:23:20 +00:00
view_template = "#{__dir__}/views/#{view}.erb"
has_layout = File.exist?(view_template) && File.open(view_template) { |f| f.first.downcase.include?('doctype') }
erb view.to_sym, locals: { referrer: request.referrer }, layout: !has_layout
2010-02-12 13:41:41 +00:00
end
2009-11-24 20:32:25 +00:00
post '/form' do
2019-05-08 23:03:57 +00:00
self.class.form_post_count += 1
%(
<pre id="content_type">#{request.content_type}</pre>
<pre id="results">#{params.fetch(:form, {}).merge('post_count' => self.class.form_post_count).to_yaml}</pre>
)
2009-11-17 22:36:27 +00:00
end
2009-11-12 16:07:43 +00:00
post '/upload_empty' do
if params[:form][:file].nil?
"Successfully ignored empty file field. Content type was #{request.content_type}"
else
'Something went wrong.'
end
end
2009-11-12 16:07:43 +00:00
post '/upload' do
2019-12-22 19:02:00 +00:00
buffer = []
buffer << "Content-type: #{params.dig(:form, :document, :type)}"
buffer << "File content: #{params.dig(:form, :document, :tempfile).read}"
buffer.join(' | ')
rescue StandardError
'No file uploaded'
2009-11-12 16:07:43 +00:00
end
post '/upload_multiple' do
2019-12-22 19:02:00 +00:00
docs = params.dig(:form, :multiple_documents)
buffer = [docs.size.to_s]
docs.each do |doc|
buffer << "Content-type: #{doc[:type]}"
buffer << "File content: #{doc[:tempfile].read}"
end
2019-12-22 19:02:00 +00:00
buffer.join(' | ')
rescue StandardError
'No files uploaded'
end
2019-05-08 23:03:57 +00:00
get '/apple-touch-icon-precomposed.png' do
halt(404)
end
2022-05-01 00:02:14 +00:00
2019-05-08 23:03:57 +00:00
class << self
attr_accessor :form_post_count
end
@form_post_count = 0
2009-11-08 00:13:16 +00:00
end
2018-03-01 00:11:41 +00:00
Rack::Handler::Puma.run TestApp, Port: 8070 if $PROGRAM_NAME == __FILE__