Vient de passer du concombre + Webrat au concombre + Capybara et je me demande comment vous pouvez POST Contenu à une URL à Capybara.
Dans Cucumber + Webrat, j'ai pu avoir une étape:
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
Cependant, la documentation de Capybara mentionne:
La méthode de visite ne prend qu'un seul paramètre, la méthode de la demande est toujours obtenue.
Comment puis-je modifier mon pas de sorte que le concombre + Capybara ait un POST à l'URL?
Plus récemment, j'ai trouvé ce grand blog post . Ce qui est génial pour les cas comme Tony et où vous voulez vraiment veux Publier quelque chose dans votre Cuke:
Pour mon cas, cela est devenu:
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
Vous pourriez faire cela:
rack_test_session_wrapper = Capybara.current_session.driver
rack_test_session_wrapper.submit :post, your_path, nil
:post
Quelle quelle que soit la méthode que vous vous souciez de par exemple. :put
Ou :delete
.your_path
Avec le Rails Chemin que vous voulez, rack_test_session_wrapper.submit :delete, document_path(Document.last), nil
supprimerait le dernier document de mon application.Si votre pilote n'a pas post
(Poltergeist ne peut par exemple), vous pouvez le faire:
session = ActionDispatch::Integration::Session.new(Rails.application)
response = session.post("/mypath", my_params: "go_here")
Mais notez que cette demande se produit lors d'une nouvelle session, vous devrez donc passer par l'objet response
pour y affirmer.
Comme cela a été déclaré ailleurs, dans un test de Capybara, vous voulez généralement faire des messages en soumettant une forme comme l'utilisateur. J'ai utilisé ce qui précède pour tester ce qui arrive à l'utilisateur si A POST se produit dans une autre session (via WebSockets), un formulaire ne le couperait pas.
DOCS:
Capybara visit
_ ne reçoit que des demandes. Ceci est par conception.
Pour qu'un utilisateur effectue un POST
, il doit cliquer sur un bouton ou soumettre un formulaire. Il n'y a pas d'autre moyen de le faire avec un navigateur.
La bonne façon de tester ce comportement serait:
visit "project/:id/edit" # This will only GET
attach_file "photo", File.open('cute_photo.jpg')
click_button 'Upload' # This will POST
Si vous voulez tester une API, je recommande d'utiliser spec/request
au lieu de concombre, mais c'est juste moi.
Je sais que la réponse a déjà été acceptée, mais j'aimerais fournir une réponse mise à jour. Voici une technique à partir de Anthony Eden et Corey Haines qui passe de rack :: Test sur l'objet mondial de concombre:
Test REST API avec concombre et rack :: Test
Avec cette technique, j'ai pu envoyer directement des demandes postales dans les définitions d'étape. Tout en écrivant les définitions de l'étape, il était extrêmement utile d'apprendre le rack :: Test API de ses propres spécifications .
# 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
Bien que, pas une réponse exacte à la question, la meilleure solution pour moi a été d'utiliser Capybara pour des spécifications qui simulent l'interaction utilisateur (à l'aide de visit
) et test de rack pour les demandes d'API de test. Ils peuvent être utilisés ensemble dans la même suite de tests.
L'ajout de ce qui suit à la spécification Helper donne accès à get
, post
et autres méthodes de test de rack:
RSpec.configure do |config|
config.include Rack::Test::Methods
Vous devrez peut-être mettre les spécifications de test de rack dans un spec/requests
dossier.
Avec une application à l'aide de RSPEC 3+, vous ne souhaitez pas créer un fichier http POST avec Capybara. Capybara est destiné à émuler le comportement des utilisateurs et à accepter le contenu du comportement et de la page JS qui résulte. Une fin L'utilisateur ne formule pas http POST Demandes de ressources dans votre application, un utilisateur clique sur les boutons, clique sur les liens Ajax, glisser des éléments de gouttes, soumet des formulaires Web, etc.
Check Out ce blog post sur Capybara et autres méthodes HTTP. L'auteur fait la revendication suivante:
Avez-vous vu une mention de méthodes comme Get, Post ou Réponse? Non? C'est parce que ceux n'existent pas à Capybara. Soyons très clairs à ce sujet ... Capybara n'est pas une bibliothèque adaptée à tester les API. Voilà. Ne testez pas les API avec Capybara. Cela n'a pas été conçu pour cela.
Donc, développer une API ou non, si vous devez faire une demande HTTP POST Demande, et cela n'implique pas un élément HTML et une sorte d'événement (cliquez, faites glisser, sélectionnez, Mise en page, Quoi qu'il en soit), alors il ne devrait pas être testé avec Capybara. Si vous pouvez tester la même fonctionnalité en cliquant sur un bouton, utilisez Capybara.
Ce que vous voulez probablement, c'est spécifications de demande RSPEC . Ici, vous pouvez faire post
appels, ainsi que toute autre méthode HTTP, et affirmer les attentes sur la réponse. Vous pouvez également vous moquer des objets et des méthodes d'encrassement pour affirmer les attentes vis-à-vis des effets secondaires et d'autres comportements qui se produisent entre votre demande et la réponse.
# 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