Как вы размещаете на URL в Капибара? - PullRequest
33 голосов
/ 03 ноября 2010

Только что перешел с Cucumber + Webrat на Cucumber + Capybara, и мне интересно, как вы можете размещать контент на URL в Capybara.

В Cucumber + Webrat я смог сделать шаг:

When /^I send "([^\"]*)" to "([^\"]*)"$/ do |file, project|
  proj = Project.find(:first, :conditions => "name='#{project}'")
  f = File.new(File.join(::Rails.root.to_s, file))
  visit "project/" + proj.id.to_s + "/upload",
        :post, {:upload_path => File.join(::Rails.root.to_s, file)}
end

Однако в документации на Capybara упоминается:

Метод посещения занимает всего один раз параметр, метод запроса всегда GET. всегда GET.

Как мне изменить мой шаг, чтобы Cucumber + Capybara выполнял POST для URL?

Ответы [ 7 ]

22 голосов
/ 08 марта 2012

Вы можете сделать это:

rack_test_session_wrapper = Capybara.current_session.driver
rack_test_session_wrapper.submit :post, your_path, nil
  • Вы можете заменить :post тем методом, который вам важен, например :put или :delete.
  • Заменить your_path с указанием пути Rails, например, rack_test_session_wrapper.submit :delete, document_path(Document.last), nil удалит последний документ в моем приложении.
22 голосов
/ 11 апреля 2011

Совсем недавно я нашел этот отличный пост в блоге .Что отлично подходит для таких дел, как Тони, и где вы действительно хотите опубликовать что-то в своем кьюке:

Для моего случая это стало:

def send_log(file, project)
  proj = Project.find(:first, :conditions => "name='#{project}'")
  f = File.new(File.join(::Rails.root.to_s, file))
  page.driver.post("projects/" + proj.id.to_s + "/log?upload_path=" + f.to_path)
  page.driver.status_code.should eql 200
end
9 голосов
/ 22 июня 2014

Если у вашего драйвера нет post (например, у Poltergeist нет), вы можете сделать это:

session = ActionDispatch::Integration::Session.new(Rails.application)
response = session.post("/mypath", my_params: "go_here")

Но обратите внимание, что этот запрос происходит в новом сеансе, поэтому вычтобы подтвердить его, придется пройти через объект response.

Как было сказано в другом месте, в тесте на Capybara вы обычно хотите выполнять POST, отправляя форму, как пользователь.Я использовал вышесказанное, чтобы проверить, что происходит с пользователем, если POST происходит в другом сеансе (через WebSockets), поэтому форма его не обрезает.1013 *http://api.rubyonrails.org/classes/ActionDispatch/Integration/Session.html

http://api.rubyonrails.org/classes/ActionDispatch/Integration/RequestHelpers.html
9 голосов
/ 03 ноября 2010

Capybara visit выполняет только запросы GET. Это по замыслу.

Чтобы пользователь мог выполнить POST, он должен нажать кнопку или отправить форму. Нет другого способа сделать это с браузером.

Правильный способ проверить это поведение:

visit "project/:id/edit" # This will only GET
attach_file "photo", File.open('cute_photo.jpg')
click_button 'Upload' # This will POST

Если вы хотите протестировать API, я рекомендую использовать spec/request вместо огурца, но это только я.

5 голосов
/ 01 ноября 2011

Я знаю, что ответ уже принят, но я хотел бы предоставить обновленный ответ. Вот методика Энтони Идена и Кори Хейнса , которая передает Rack :: Test объекту Cucumber's World:

Тестирование API REST с огурцом и стойкой :: Тест

С помощью этой техники я смог напрямую отправлять почтовые запросы в пределах определений шагов. При написании определений шагов было чрезвычайно полезно изучить API Rack :: Test из его собственных specs .

# feature
  Scenario: create resource from one time request
    Given I am an admin
    When I make an authenticated request for a new resource
    Then I am redirected  
    And I see the message "Resource successfully created" 

# step definitions using Rack::Test
When /^I make an authenticated request for a new resource$/ do
  post resources_path, :auth_token => @admin.authentication_token
  follow_redirect!
end

Then /^I am redirected$/ do
  last_response.should_not be_redirect
  last_request.env["HTTP_REFERER"].should include(resources_path)
end

Then /^I see the message "([^"]*)"$/ do |msg|
  last_response.body.should include(msg)
end
2 голосов
/ 28 мая 2015

Хотя это не точный ответ на этот вопрос, лучшим решением для меня было использование Capybara для спецификаций, имитирующих взаимодействие с пользователем (используя visit), и Rack Test для тестирования API-запросов. Они могут использоваться вместе в одном наборе тестов.

Добавление следующего к помощнику спецификаций дает доступ к get, post и другим методам тестирования в стойке:

RSpec.configure do |config|
  config.include Rack::Test::Methods

Возможно, вам понадобится поместить спецификации Rack Test в папку spec/requests.

1 голос
/ 09 апреля 2017

В приложении, использующем RSpec 3+, вы не захотите делать HTTP-запрос POST с Capybara. Capybara для эмуляции поведения пользователя и принятия поведения JS и содержимого страницы, которое в результате. Конечный пользователь не формирует HTTP-запросы POST на ресурсы в вашем приложении, пользователь нажимает кнопки, щелкает ajax-ссылки, перетаскивает n элементов, отправляет веб-формы и т. Д.

Ознакомьтесь с этим сообщением в блоге о Capybara и других методах HTTP. Автор предъявляет следующие претензии:

Вы видели какие-либо упоминания о таких методах, как получение, публикация или ответ? Нет? Это потому, что их нет в Капибаре. Давайте проясним это ... Capybara - это не библиотека, подходящая для тестирования API. Там у вас есть это. Не тестируйте API с помощью Capybara. Он не был предназначен для этого.

Итак, разрабатываете API или нет, если вам нужно сделать явный HTTP-запрос POST, и он не включает в себя HTML-элемент и какое-то событие (щелчок, перетаскивание, выбор, фокусировка, что угодно), тогда он не должен не тестируйся с капибарой. Если вы можете протестировать ту же функцию, нажав какую-то кнопку, используйте Capybara.

То, что вы, вероятно, хотите, это Спецификации запроса RSpec . Здесь вы можете совершать post вызовы, а также любые другие методы HTTP и утверждать ожидания в ответе. Вы также можете смоделировать n объектов-заглушек и методы, чтобы утверждать ожидания в отношении побочных эффектов и других действий, которые происходят между вашим запросом и ответом.

# spec located in spec/requests/project_file_upload_spec.rb
require "rails_helper"

RSpec.describe "Project File Upload", type: :request do

  let(:project) { create(:project) }
  let(:file)    { File.new(File.join(::Rails.root.to_s, 'path/to/file.ext')) } # can probably extract this to a helper...

  it "accepts a file uploaded to a Project resource" do

    post "project/#{project.id}/upload", upload_path: file

    expect(response).to be_success
    expect(project.file?).to eq(true)
    # expect(project.file).not_to eq(nil)
    expect(response).to render_template(:show)
  end

end
...