Mike Glaz
Mike Glaz

Reputation: 5382

How do I select a value from a database populated dropdown with Capybara?

I have 2 models: Venue and Event. Venue has_many :events and Event belongs_to :venue.

My events/new form has the following fields

Now I'm trying to test this with RSpec and Capybara. Here's my feature:

require 'spec_helper'

feature "Events" do
  let(:venue) { FactoryGirl.create(:venue) }
  let(:event) { FactoryGirl.create(:event, venue: venue) }

  scenario "Creating event as guest" do
    visit root_path
    click_link "Submit Event"
    fill_in "Title", with: event.title
    click_button "Submit"
    expect(page).to have_content("Event has been created.")
    expect(page).to have_content(event.title)
  end
end

My factories look like this:

FactoryGirl.define do
  factory :event do
    date "2014-02-27"
    time "10:00am"
    title "Slayer"
  end
end

FactoryGirl.define do
  factory :venue do
    name "Example Venue"
    url "http://www.example.com"
    address "123 Main St., Chicago, IL"
  end
end

When I run this spec I get the following error:

 Failure/Error: click_button "Submit"
 ActionView::Template::Error:
   Couldn't find Venue without an ID

I'm guessing this has something to do with the fact that the Venue field is not populated in the test environment?

Upvotes: 0

Views: 471

Answers (1)

phoet
phoet

Reputation: 18835

using let is lazy, so your database call will get executed here:

  scenario "Creating event as guest" do
    visit root_path
    click_link "Submit Event"
    fill_in "Title", with: event.title # <------------------- evaluated!
    click_button "Submit"
    expect(page).to have_content("Event has been created.")
    expect(page).to have_content(event.title)
  end

what you probably want is this:

feature "Events" do
  background do
    @event = FactoryGirl.create(:event, venue: FactoryGirl.create(:venue))
  end

  scenario "Creating event as guest" do
    visit root_path
    click_link "Submit Event"
    fill_in "Title", with: @event.title
    click_button "Submit"
    expect(page).to have_content("Event has been created.")
    expect(page).to have_content(@event.title)
  end
end

you could also use let! which executes directly, but i think the setup block is much clearer.

Upvotes: 2

Related Questions