我需要使用Capybara和Selenium测试文件上传页面。
我写了这个测试:
require 'rails_helper'
describe 'Images', type: :feature do
before(:each) do
@user = create(:user)
visit '/users/sign_in'
fill_in 'sing-in-email-input', with: @user.email
fill_in 'sign-in-password-input', with: @user.password
click_button 'btn-sign-in'
visit '/categories'
click_on 'btn-new-category'
expect(current_path) == new_category_path
fill_in 'category_name', with: 'Test'
click_button 'btn-create category'
visit '/categories'
first('.fa', :visible => false).click
expect(current_path) == category_path(id: Category.last.slug.to_s)
end
it 'should allow a registered user to create image and go to it page', js: true do
click_on 'btn-upload-images'
expect(current_path) == new_image_path(id: Category.last.slug.to_s)
attach_file('image[image]',
File.join(Rails.root, '/spec/fixtures/solnce-kosmos-merkuriy.jpg'), :visible => false)
click_on('btn-upload-img')
end
end
我无法继续编写此测试并检查此图片是否已成功上传,因为在此行:
click_on(' BTN上传-IMG&#39)
我收到了这个错误:
Failure/Error: raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}"
ActionController::RoutingError:
No route matches [GET] "/home/Anton-S/RubymineProjects/rails_projects/gallery/spec/support/uploads/image/image/8790/solnce-kosmos-merkuriy.jpg"
# /var/lib/gems/2.3.0/gems/railties-5.1.4/lib/rails/rack/logger.rb:36:in `call_app'
# /var/lib/gems/2.3.0/gems/railties-5.1.4/lib/rails/rack/logger.rb:24:in `block in call'
# /var/lib/gems/2.3.0/gems/railties-5.1.4/lib/rails/rack/logger.rb:24:in `call'
# /var/lib/gems/2.3.0/gems/rack-2.0.3/lib/rack/method_override.rb:22:in `call'
# /var/lib/gems/2.3.0/gems/rack-2.0.3/lib/rack/runtime.rb:22:in `call'
# /var/lib/gems/2.3.0/gems/rack-2.0.3/lib/rack/sendfile.rb:111:in `call'
# /var/lib/gems/2.3.0/gems/railties-5.1.4/lib/rails/engine.rb:522:in `call'
# /var/lib/gems/2.3.0/gems/rack-2.0.3/lib/rack/urlmap.rb:68:in `block in call'
# /var/lib/gems/2.3.0/gems/rack-2.0.3/lib/rack/urlmap.rb:53:in `each'
# /var/lib/gems/2.3.0/gems/rack-2.0.3/lib/rack/urlmap.rb:53:in `call'
# /var/lib/gems/2.3.0/gems/capybara-2.16.1/lib/capybara/server.rb:44:in `call'
# /var/lib/gems/2.3.0/gems/rack-2.0.3/lib/rack/handler/webrick.rb:86:in `service'
# ------------------
# --- Caused by: ---
# Capybara::CapybaraError:
# Your application server raised an error - It has been raised in your test code because Capybara.raise_server_errors == true
# /var/lib/gems/2.3.0/gems/capybara-2.16.1/lib/capybara/session.rb:145:in `raise_server_error!'
Finished in 17.15 seconds (files took 2.55 seconds to load)
133 examples, 1 failure
Failed examples:
rspec ./spec/features/images_spec.rb:20 # Images should allow a registered user to create image and go to it page
我已经检查过我真的有这个文件
/spec/fixtures/solnce-kosmos-merkuriy.jpg
在正确的地方。
这是我的 /config/initializers/carrierwave.rb
if Rails.env.test? || Rails.env.cucumber?
CarrierWave.configure do |config|
config.storage = :file
config.enable_processing = false
end
# make sure our uploader is auto-loaded
ImageUploader
# use different dirs when testing
CarrierWave::Uploader::Base.descendants.each do |klass|
next if klass.anonymous?
klass.class_eval do
def cache_dir
"#{Rails.root}/spec/support/uploads/tmp"
end
def store_dir
"#{Rails.root}/spec/support/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
end
end
我的 rails_helper.rb
require 'support/factory_bot'
require 'spec_helper'
require 'shoulda/matchers'
require 'capybara/rspec'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
ActiveRecord::Migration.maintain_test_schema!
module DeviseRequestSpecHelpers
include Warden::Test::Helpers
def sign_in(resource_or_scope, resource = nil)
resource ||= resource_or_scope
scope = Devise::Mapping.find_scope!(resource_or_scope)
login_as(resource, scope: scope)
end
def sign_out(resource_or_scope)
scope = Devise::Mapping.find_scope!(resource_or_scope)
logout(scope)
end
end
RSpec.configure do |config|
Capybara.ignore_hidden_elements = false
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.infer_spec_type_from_file_location!
config.filter_rails_from_backtrace!
config.include Devise::Test::ControllerHelpers, type: :controller
config.include DeviseRequestSpecHelpers, type: :request
end
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails
end
end
我的 spec_helper.rb
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.shared_context_metadata_behavior = :apply_to_host_groups
end
此图片上传页面的查看模板:
.row.main-new-image
= form_for @image, url: create_image_path, html: {multipart: true, method: :post, remote: true } do |form|
#new_image_error_explanation
.field
.p.text-center
%span.btn.btn-new-image{id: 'new-image-button'}
%p#p-new-image-button Choose image
\#{form.file_field :image, id: 'new-image-id'}
.field
= form.hidden_field :user_id, value: current_user.id
.actions
.p.text-center
= form.submit 'Upload', class: 'btn button-upload-img', id: 'btn-upload-img'
我所有的其他Capybara和RSpec测试都运行良好。
请帮助我了解此问题的原因以及如何解决此问题并在将来进行预防。
如果有助于解决此问题,我可以提供更多信息。
更新1
在我阅读Thomas Walpole的评论后,我决定更新我的代码并尝试其他一些功能。 我包括新宝石
gem' database_cleaner'
此外,我添加了新代码以清除测试上传的代码。 此处已更新 rails_helper.rb
require 'support/factory_bot'
require 'spec_helper'
require 'shoulda/matchers'
require 'capybara/rspec'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
ActiveRecord::Migration.maintain_test_schema!
module DeviseRequestSpecHelpers
include Warden::Test::Helpers
def sign_in(resource_or_scope, resource = nil)
resource ||= resource_or_scope
scope = Devise::Mapping.find_scope!(resource_or_scope)
login_as(resource, scope: scope)
end
def sign_out(resource_or_scope)
scope = Devise::Mapping.find_scope!(resource_or_scope)
logout(scope)
end
end
RSpec.configure do |config|
Capybara.javascript_driver = :selenium
Capybara.ignore_hidden_elements = true
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(app, browser: :firefox)
end
config.include Capybara::DSL
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
config.around(:each) do |example|
DatabaseCleaner.cleaning do
example.run
end
end
config.after(:all) do
if Rails.env.test?
FileUtils.rm_rf(Dir["#{Rails.root}/spec/support/uploads"])
end
end
config.infer_spec_type_from_file_location!
config.filter_rails_from_backtrace!
config.include Devise::Test::ControllerHelpers, type: :controller
config.include DeviseRequestSpecHelpers, type: :request
end
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails
end
end
这是我更新的测试
require 'rails_helper'
describe 'Images', type: :feature do
before(:each) do
@user = create(:user)
visit '/users/sign_in'
fill_in 'sing-in-email-input', with: @user.email
fill_in 'sign-in-password-input', with: @user.password
click_button 'btn-sign-in'
visit '/categories'
click_on 'btn-new-category'
have_current_path(new_category_path)
fill_in 'category_name', with: 'Test'
click_button 'btn-create category'
visit '/categories'
first('.fa', :visible => false).click
have_current_path(category_path(id: Category.last.slug.to_s))
end
#ISSUE WITH
it 'should allow a registered user to create image and go to it page', :driver => :selenium do
click_on 'btn-upload-images'
have_current_path(new_image_path(id: Category.last.slug.to_s))
attach_file('image[image]',
File.join(Rails.root, '/spec/fixtures/solnce-kosmos-merkuriy.jpg'), :visible => false)
click_on('btn-upload-img')
end
end
正如Thomas Walpole告诉我的那样,我检查了测试日志然后看了下(关于当前的测试):
Started GET "/en/categories/test/new_image" for 127.0.0.1 at 2018-01-30 14:33:26 +0200
Processing by ImagesController#new as HTML
Parameters: {"locale"=>"en", "id"=>"test"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 22], ["LIMIT", 1]]
(0.2ms) SAVEPOINT active_record_2
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 22], ["LIMIT", 1]]
SQL (0.3ms) INSERT INTO "user_actions" ("user_id", "action_type", "url", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["user_id", 22], ["action_type", "navigation"], ["url", "http://127.0.0.1:38226/en/categories/test/new_image"], ["created_at", "2018-01-30 12:33:26.645909"], ["updated_at", "2018-01-30 12:33:26.645909"]]
(0.1ms) RELEASE SAVEPOINT active_record_2
Rendering images/new.html.haml within layouts/application
Rendered images/_form.html.haml (5.2ms)
Rendered images/new.html.haml within layouts/application (7.5ms)
Category Load (1.1ms) SELECT DISTINCT categories.*, COUNT(images.*) AS images_count, categories.*, COUNT(likes.*) AS likes_count, categories.*, COUNT(comments.*) AS comments_count FROM "categories" LEFT OUTER JOIN "images" ON "images"."category_id" = "categories"."id" LEFT OUTER JOIN "images" "images_categories_join" ON "images_categories_join"."category_id" = "categories"."id" LEFT OUTER JOIN "likes" ON "likes"."image_id" = "images_categories_join"."id" LEFT OUTER JOIN "images" "images_categories_join_2" ON "images_categories_join_2"."category_id" = "categories"."id" LEFT OUTER JOIN "comments" ON "comments"."image_id" = "images_categories_join_2"."id" GROUP BY categories.id ORDER BY images_count DESC, likes_count DESC, comments_count DESC LIMIT $1 [["LIMIT", 5]]
Rendered layouts/_header.html.haml (4.3ms)
Rendered layouts/_footer.haml (0.0ms)
Completed 200 OK in 21ms (Views: 12.6ms | ActiveRecord: 2.1ms)
Category Load (0.6ms) SELECT "categories".* FROM "categories" ORDER BY "categories"."id" DESC LIMIT $1 [["LIMIT", 1]]
Started POST "/en/categories/test/create_image" for 127.0.0.1 at 2018-01-30 14:33:26 +0200
Processing by ImagesController#create as JS
Parameters: {"utf8"=>"✓", "image"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x0000000ae4e008 @tempfile=#<Tempfile:/tmp/RackMultipart20180130-28977-1nptliu.jpg>, @original_filename="solnce-kosmos-merkuriy.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"image[image]\"; filename=\"solnce-kosmos-merkuriy.jpg\"\r\nContent-Type: image/jpeg\r\n">, "user_id"=>"22"}, "commit"=>"Upload", "locale"=>"en", "id"=>"test"}
Category Load (0.2ms) SELECT "categories".* FROM "categories" WHERE "categories"."slug" = $1 LIMIT $2 [["slug", "test"], ["LIMIT", 1]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 22], ["LIMIT", 1]]
(0.3ms) SAVEPOINT active_record_2
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 22], ["LIMIT", 1]]
Category Load (0.2ms) SELECT "categories".* FROM "categories" WHERE "categories"."id" = $1 LIMIT $2 [["id", 18], ["LIMIT", 1]]
SQL (0.4ms) INSERT INTO "images" ("image", "category_id", "created_at", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["image", "solnce-kosmos-merkuriy.jpg"], ["category_id", 18], ["created_at", "2018-01-30 12:33:26.945577"], ["updated_at", "2018-01-30 12:33:26.945577"], ["user_id", 22]]
(0.2ms) RELEASE SAVEPOINT active_record_2
Redirected to http://127.0.0.1:38226/en/categories/test/12
Completed 200 OK in 22ms (ActiveRecord: 1.6ms)
Started GET "/en/categories/test/12" for 127.0.0.1 at 2018-01-30 14:33:26 +0200
Processing by ImagesController#show as HTML
Parameters: {"locale"=>"en", "id"=>"test", "image_id"=>"12"}
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 22], ["LIMIT", 1]]
(0.1ms) SAVEPOINT active_record_2
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 22], ["LIMIT", 1]]
SQL (0.3ms) INSERT INTO "user_actions" ("user_id", "action_type", "url", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["user_id", 22], ["action_type", "navigation"], ["url", "http://127.0.0.1:38226/en/categories/test/12"], ["created_at", "2018-01-30 12:33:26.966397"], ["updated_at", "2018-01-30 12:33:26.966397"]]
(0.1ms) RELEASE SAVEPOINT active_record_2
Category Load (0.1ms) SELECT "categories".* FROM "categories" WHERE "categories"."slug" = $1 LIMIT $2 [["slug", "test"], ["LIMIT", 1]]
Image Load (0.2ms) SELECT "images".* FROM "images" WHERE "images"."category_id" = $1 AND "images"."id" = $2 LIMIT $3 [["category_id", 18], ["id", 12], ["LIMIT", 1]]
Like Load (0.2ms) SELECT "likes".* FROM "likes" WHERE "likes"."image_id" = $1 AND "likes"."user_id" = $2 LIMIT $3 [["image_id", 12], ["user_id", 22], ["LIMIT", 1]]
Rendering images/show.html.haml within layouts/application
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 22], ["LIMIT", 1]]
(0.3ms) SELECT COUNT(*) FROM "comments" WHERE "comments"."image_id" = $1 [["image_id", 12]]
Like Load (0.2ms) SELECT "likes".* FROM "likes" WHERE "likes"."user_id" = $1 AND "likes"."image_id" = 12 LIMIT $2 [["user_id", 22], ["LIMIT", 1]]
(0.3ms) SELECT COUNT(*) FROM "likes" WHERE "likes"."image_id" = $1 [["image_id", 12]]
Rendered likes/_like.html.haml (3.2ms)
Rendered likes/_like_form.html.haml (7.3ms)
Rendered comments/_comments.html.haml (2.7ms)
Rendered comments/_comments_container.html.haml (5.1ms)
Rendered images/show.html.haml within layouts/application (25.6ms)
Category Load (1.3ms) SELECT DISTINCT categories.*, COUNT(images.*) AS images_count, categories.*, COUNT(likes.*) AS likes_count, categories.*, COUNT(comments.*) AS comments_count FROM "categories" LEFT OUTER JOIN "images" ON "images"."category_id" = "categories"."id" LEFT OUTER JOIN "images" "images_categories_join" ON "images_categories_join"."category_id" = "categories"."id" LEFT OUTER JOIN "likes" ON "likes"."image_id" = "images_categories_join"."id" LEFT OUTER JOIN "images" "images_categories_join_2" ON "images_categories_join_2"."category_id" = "categories"."id" LEFT OUTER JOIN "comments" ON "comments"."image_id" = "images_categories_join_2"."id" GROUP BY categories.id ORDER BY images_count DESC, likes_count DESC, comments_count DESC LIMIT $1 [["LIMIT", 5]]
Rendered layouts/_header.html.haml (4.6ms)
Rendered layouts/_footer.haml (0.1ms)
Completed 200 OK in 43ms (Views: 30.0ms | ActiveRecord: 4.1ms)
Started GET "/home/Anton-S/RubymineProjects/rails_projects/gallery/spec/support/uploads/image/image/12/solnce-kosmos-merkuriy.jpg" for 127.0.0.1 at 2018-01-30 14:33:27 +0200
(0.2ms) ROLLBACK TO SAVEPOINT active_record_1
(0.1ms) ROLLBACK
(0.1ms) BEGIN
(0.1ms) COMMIT
(0.0ms) BEGIN
(0.0ms) SAVEPOINT active_record_1
(0.1ms) SAVEPOINT active_record_2
据我了解,图片已成功上传。 但我仍然得到这个错误
Failure/Error: raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}"
ActionController::RoutingError:
No route matches [GET] "/home/Anton-S/RubymineProjects/rails_projects/gallery/spec/support/uploads/image/image/12/solnce-kosmos-merkuriy.jpg"
更新2
不幸的是,我找到的唯一解决方案是进入 的 /config/environments/test.rb
config.action_dispatch.show_exceptions = true
但我仍然认为有更好的解决方案。
答案 0 :(得分:1)
因此,从日志中,我们可以看到文件已成功上传。
问题在于,当展示页面呈现时,图像将被添加到HTML中,其中包含'/ home / Anton-S / RubymineProjects / rails_projects / gallery / spec / support / uploads / image / image / 12 /等网址solnce-kosmos-merkuriy.jpg'这将无效,因为rails应用程序不会响应来自应用程序根目录中public
目录之外的随机文件。这样做将是一个巨大的安全问题。最简单的解决方案是将图像存储到public
目录中,以便rails应用程序将它们作为静态资源提供。
def cache_dir
"public/test/uploads/tmp"
end
def store_dir
"public/test/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
注意:我还评论了您对have_current_path
匹配器的使用。