代码之家  ›  专栏  ›  技术社区  ›  ruby_dev

水豚上传图像问题

  •  0
  • ruby_dev  · 技术社区  · 8 年前

    我需要用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
    

    我无法继续编写此测试,并检查此图像是否已成功上载,因为在此行中:

    单击('btn-upload-img')

    我遇到了以下错误:

    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
    

    我已经检查过了我真的有这个文件

    /规格/固定装置/solnce kosmos merkuriy。jpg公司

    在正确的地方。

    这是我的 /配置/初始化器/载波。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\u助手。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\u辅助对象。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'
    

    我所有其他的水豚和RSpec测试都很好。

    请帮助我了解这个问题的原因,以及如何解决和预防。

    如果能帮助解决这个问题,我可以提供更多信息。

    更新1

    在我读了托马斯·沃尔波尔的评论后,我决定更新我的代码并尝试其他一些功能。 我包括新宝石

    gem“database\u cleaner”

    此外,我还添加了新代码以清除测试上载的代码。 此处已更新 rails\u助手。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
    

    正如托马斯·沃尔波尔(ThomasWalpole)告诉我的,我检查了测试日志,然后看到了下一个(关于当前测试):

    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

    不幸的是,我找到的唯一解决办法就是 /配置/环境/测试。rb型

    config.action_dispatch.show_exceptions = true
    

    但我仍然认为有更好的解决办法。

    1 回复  |  直到 5 年前
        1
  •  1
  •   Thomas Walpole    8 年前

    因此,从日志中,我们可以看到文件正在成功上载。

    问题是,当显示页面呈现时,图像被添加到HTML中,URL为“/主页/Anton-S/RubyMineProject/rails\u项目/库/规范/支持/上传/图像/图像/12/solnce kosmos merkuriy”。“jpg”不会起作用,因为rails应用程序不会响应来自外部的随机文件 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 匹配器。