método indefinido `visita 'ao usar RSpec e Capybara em trilhos

89

Não consigo fazer a capivara funcionar com rspec. Isso me dá este erro:

undefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_1:0x16529f8 @example=nil>

Eu sei que há muitos posts sobre isso, mas nenhuma das soluções está funcionando para mim. A maioria deles envolve as especificações que não estão em / spec / features - no qual o meu está.

Primeiro o erro:

$bundle exec rspec spec
F

Failures:

  1) security signs users in
     Failure/Error: visit "/sessions/new"
     NoMethodError:
       undefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_1:0x16529f8 @example=nil>
     # ./spec/features/security_spec.rb:4:in `(root)'

 Finished in 0.006 seconds
 1 example, 1 failure

Failed examples:

rspec ./spec/features/security_spec.rb:3 # security signs users in

Acho importante notar que no início eu estava usando o URL Helper 'new_sessions_path' e ele continuava me dando um erro undefined local variable or method 'new_sessions_path'. Eu sei que é válido porque:

$ rake routes
logout_sessions GET    /sessions/logout(.:format) sessions#logout
       sessions POST   /sessions(.:format)        sessions#create
   new_sessions GET    /sessions/new(.:format)    sessions#new
      contracts POST   /contracts(.:format)       contracts#create
  new_contracts GET    /contracts/new(.:format)   contracts#new
 edit_contracts GET    /contracts/edit(.:format)  contracts#edit
                GET    /contracts(.:format)       contracts#show
                PUT    /contracts(.:format)       contracts#update
                DELETE /contracts(.:format)       contracts#destroy
           root        /                          contracts#index

Meu Gemfile:

source 'https://rubygems.org'

gem 'rails', '3.2.11'
gem 'execjs'

group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'
  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'
gem 'activerecord-oracle_enhanced-adapter', '~> 1.4.1'
gem 'jruby-openssl'
gem 'therubyrhino'
gem 'kaminari'
gem 'nokogiri'

group :development do
  gem 'warbler'
end

group :test do
  gem 'rspec-rails'
  gem 'capybara'
  gem 'activerecord-jdbcsqlite3-adapter'
end

spec_helper.rb dentro de my_app / spec:

# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'

# Capybara integration
require 'capybara/rspec'
require 'capybara/rails'

# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

RSpec.configure do |config|
  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  # config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.use_transactional_fixtures = true
  config.infer_base_class_for_anonymous_controllers = false
  config.order = "random"
  # Include path helpers
  config.include Rails.application.routes.url_helpers
end

my_app / spec / features / security_spec.rb:

describe "security", :type => :feature do
  it "signs users in" do
    visit "/sessions/new"
    fill_in "username", :with => "user"
    fill_in "password", :with => "pass"
    click_button "Sign In"

    page.should have_content('Login Successful')
  end
end

Tentei definir o teste acima com e sem :type => :feature. Não faz diferença de qualquer maneira. Alguma ideia do que devo tentar a seguir?

lightswitch05
fonte
Possível duplicata de Capivara: método indefinido 'visita'
mlt
1
@mlt no primeiro parágrafo eu disse: "Eu sei que há muitos posts sobre isso, mas nenhuma das soluções está funcionando para mim. A maioria deles envolve as especificações não estarem em / spec / features - nas quais a minha está." Este parágrafo se refere especificamente à pergunta para a qual você tem um link Esta pergunta não só tem votos mais altos, mas também vem com uma solução - que é diferente da resposta com maior votação (não solução) postada em sua pergunta vinculada.
lightswitch05

Respostas:

201

Tente adicionar:

  config.include Capybara::DSL

ao seu bloco de configuração.

# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'

# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

RSpec.configure do |config|
  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  # config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.use_transactional_fixtures = true
  config.infer_base_class_for_anonymous_controllers = false
  config.order = "random"
  # Include path helpers
  config.include Rails.application.routes.url_helpers

  config.include Capybara::DSL

end
Kocur4d
fonte
Não, exatamente o mesmo problema, sem mudança aparente
lightswitch05
8
Isso funcionou para mim - muito obrigado. Eu não precisei fazer isso em meus outros projetos. Que circunstâncias tornariam isso necessário em um projeto, mas não em outro? Além disso, o que exatamente isso está fazendo?
Peter Berg
1
Funcionou para mim também. Muito obrigado!
Marian Zagoruiko
Meu arquivo já tinha o 'spec_helper' que foi verificado como a resposta para este problema, mas funcionou para mim. Obrigado!
sixty4bit
Isso não funciona para mim: recebo uma mensagem de erro que Capybaraé uma constante indefinida. Meus testes de pepino estão usando Capivara perfeitamente.
digitig
53

Adicionar require 'rails_helper'no topo do meu recurso acabou resolvendo meu problema:

require 'rails_helper'

describe "security", :type => :feature do

  it "signs users in" do
    visit new_sessions_path
    fill_in "username", :with => "user"
    fill_in "password", :with => "pass"
    click_button "Sign In"

    page.should have_content('Login Successful')
  end
end

Isso me parece estranho, já que todos os exemplos que vi de rspec e capivara não tinham esse requerimento, mas tudo bem. Problema resolvido.

Resposta original (versões mais antigas do rspec)

require 'spec_helper'é usado por versões mais antigas do RSpec. A melhor resposta seria require 'rails_helper'.

lightswitch05
fonte
4
Você deve colocar a parte de atualização no topo de sua postagem.
nistvan
É realmente uma má maneira de aceitar a sua própria resposta, embora a resposta do Kocur4d seja mais precisa (e esquecer de incluir o rails_helper.rb não seria o problema mais comum). Você deve alterar a resposta aceita, pois sem a alteração da configuração feita antes de incluí-la, você ainda teria o mesmo erro.
Randmin
35

Desde o Capybara 2.0, é necessário usar a pasta spec / features. Os comandos do Capybara não funcionam mais na pasta spec / requests.

Thillai Narayanan
fonte
2
Como minha pergunta afirma, meu teste de capivara já estava localizado em spec/features. Mas esse é um ponto válido para outras pessoas que podem estar tendo problemas.
lightswitch05
Acho útil criar o diretório mkdir spec/featurese criar um link simbólico ln -s spec/features spec/requests. Desta forma, quaisquer testes gerados serão colocados no diretório de recursos.
omarshammas
Obrigado @ThillaiNarayanan, esse era o meu problema seguindo um guia de configuração antigo, mas em uma versão mais recente do Capivara
VegaStudios
5

Tente realizar toda a configuração em um beforebloco:

spec / features / security_spec.rb

describe "security" do
  before do
    visit "/sessions/new"
    fill_in "username", :with => "user"
    fill_in "password", :with => "pass"
    click_button "Sign In"
  end

  it "signs users in" do
    page.should have_content('Login Successful')
  end
end
Paul Fioravanti
fonte
2
Na verdade, essa é uma causa comum do erro. A visitfunção está disponível apenas dentro de um itbloco. Fonte
lightswitch05
4
Não é verdade - o código em um beforebloco é executado no contexto de exemplo, então visitfuncionará lá tão bem quanto em um itbloco.
zetético
2
@ user912563, no final das contas, já que você resolveu seu próprio problema, minha resposta realmente se torna uma sugestão de estilo mais do que qualquer outra coisa (configurar o código em beforeblocos é como escrevo minhas especificações e elas funcionam sem erros ;-)), então eu acho é justo aceitar sua própria resposta.
Paul Fioravanti
Obrigado @zetetic e @Paul-Firavanti - não sabia beforeainda estava dentro do itcontexto. Usar isso tornará meus outros testes que exigem login muito mais limpos
lightswitch05
Isso me ajudou porque eu sou um novato e não tinha teste embrulhado "" do ... fim.
Danny
3

Eu também tive esse problema,

Adicionar require 'rails_helper' na parte superior do meu recurso acabou corrigindo meu problema:

require 'rails_helper'

RSpec.describe "Products", type: :request do
 describe "GET /products" do
 it "display tasks" do
  Product.create!(:name => "samsung")
  visit products_path
  page.should have_content("samsung")
  #expect(response).to have_http_status(200)
  end
 end
end

E adicione o 'config.include Capybara :: DSL' em rails_helper.rb

RSpec.configure do |config|

 config.fixture_path = "#{::Rails.root}/spec/fixtures"

 config.use_transactional_fixtures = true

 config.infer_spec_type_from_file_location!

 config.include Capybara::DSL

end
Sathibabu P
fonte
Adicionar essa linha de configuração funcionou para mim. É estranho porque eu estava recebendo o erro em um dos meus arquivos de especificação, mas não em outro arquivo de especificação, e ambos chamaram os mesmos métodos capy (e ambos exigiam rails_helper)
Jonathan Tuzman