Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capybara: ElementNotFound: unable to find field name on a multi-part form

I'm having difficulty isolating the problem with my attempt at this feature spec.

require 'spec_helper'

feature 'Add Employee', type: :feature do 
  scenario 'with valid information' do
    # visit setup_add_employees_path
    visit '/setup/add_employees'
    # save_and_open_page
    fill_in "First Name", with: 'Test'
    fill_in 'Last Name', with: 'Employee'
    fill_in 'Email', with: '[email protected]'
    # fill_in , with: '[email protected]'

    # expect(page).to find_field('First Name').value
  end
end

This is step 2 of a multi-part form, I have the first step's spec written and its working fine. However in this spec, using fill_in for the form fields does not.

Here are my associated files for this spec:

# add_employees.html.haml

= render "partials/nav_left_setup"
- model_class = Invitation.new.class
#alert_message
.page-header
  %h1 Invite Your Employees
%p.lead Now it's time to add your employees to HuddleHR. We'll send an email to your employees when setup is complete. Don't worry, the email will include instructions on how to setup their account and update their personal information.
%p.lead
  If you like, you can import your employee list from an
  = succeed "." do
    %a#show_import_form{ href: "#" } Excel file

= render "partials/setup_import_employees"

= nested_form_for @account, :html => {:class => "invitation"} do |f|
  %br/
  = f.fields_for :invitations, @invitations do |invitation_form|
    = invitation_form.hidden_field :product_id, :value => "1"
    = invitation_form.text_field :first_name, :class => "input-small", :placeholder => "First Name", :required => :true
    = invitation_form.text_field :last_name, :class => "input-small", :placeholder => "Last Name", :required => :true
    %span= invitation_form.email_field :email, :class => "text_field", :placeholder => "Email Address", :required => :true
    = invitation_form.collection_select :team_id, @teams, :id, :name
    - if invitation_form.object.new_record?
      = hidden_field_tag :invitaion_new_record, "new record"
      = link_to "Delete", "javascript:void(0);", :class => "btn btn-danger  delete_invitation_row_button", :style => "margin-bottom: 12px"
    - else
      = link_to "Delete", invitation_form.object, :confirm => "Are you sure?", :method => :delete, :remote => true, :class => "btn btn-danger btn-delete destroy_duplicate_nested_form", :style => "margin-bottom: 12px"
  = f.link_to_add raw("<i class=\"icon-plus-sign icon-white\"></i> Add An Employee"), :invitations, class: "btn btn-success"
  .form-actions
    = link_to "Back", @optional_step.prv_link, class: "btn"
    = f.submit "Save & Continue", :class => "btn btn-primary"
    = link_to "Skip This Step", @optional_step.next_link, class: "btn" if @optional_step.optional == true


# The accounts_controller's create method

  def create # TODO we need to document this...
    @account = Account.new(params[:account])

    if @account.save
      # Send the account setup email to the account creator
      UserMailer.account_setup_email(current_user).deliver

      current_user.add_role!(User::ROLES[0]) # asigning the role roster_admin
      current_user.add_role!(User::ROLES[3]) # asigning the role employee

      # Sign the account up for Roster and create some inital records like:
      # Register Roster as a product the account has subscribed to.
      AccountProduct.create!(:account_id => @account.id, :product_id => Product.where(:name => "Roster").first.id)

      # Create the account holder's profile
      Profile.create!(:user_id => current_user.id, :first_name => @account.account_owner_first_name_input, :last_name => @account.account_owner_last_name_input)

      # Create their first default team so they have a place to keep people
      Team.create!(name: "Example Team", description: "This is just a placeholder team. You can rename or delete it.", account_id: @account.id, manager_id: current_user.id)

      # Create their first job description so they have a place to keep people
      JobDescription.create!(title: "Example Job Description", description: "This is just a placeholder job description. You can rename or delete it.", account_id: @account.id)

      # Create a first post for the company so they have something on their homepage...
      Post.create!(title: "Welcome to HuddleHR", body: "The simple and easy way to manage employee information in the cloud. You can invite employees, setup your org chart, fill out your profile and more.", account_id: @account.id, author_id: current_user.id, scope_id: "1")

      # Create the initial employment record
      Employment.create!(:user_id => current_user.id, :team_id => Team.find_by_account_id(@account.id).id, :effective_date => Date.today, :comment => "Initial creation of HuddleHR account owner employment record.")

      # Set the User.account_id to the created account.id
      current_user.update_attributes!(:account_id => @account.id)

      setup_steps = @account.product_setup_steps

      current_step = ProductSetupStep.where("link =? AND product_id =?", URI(request.referer).path, 1).first # Getting the current step

      if current_step
        setup_steps << ProductSetupStep.where("link =? AND product_id =?", URI(request.referer).path, 1).first
        setup_steps << ProductSetupStep.where("step_number =? AND product_id =?", 1, 1).first
        redirect_to current_step.next_link, :notice => 'Your account was successfully created.' if current_step.next_link.present?
        redirect_to account_path(@account), :notice => 'Your account was successfully created.' unless current_step.next_link.present?
      else
        redirect_to account_path(@account), :notice => 'Your account was successfully created.'
      end

    else
      render :action => "new"
    end
  end
# the imacros file, which I'm told is similar to selenium 

' Add Employee
TAG POS=1 TYPE=A ATTR=TXT:Add<SP>An<SP>Employee
TAG POS=1 TYPE=INPUT:TEXT FORM=ID:edit_account_*  ATTR=ID:account_invitations_attributes_*_first_name CONTENT=Test
TAG POS=1 TYPE=INPUT:TEXT FORM=ID:edit_account_* ATTR=ID:account_invitations_attributes_*_last_name CONTENT=Employee{{!VAR1}}
TAG POS=1 TYPE=INPUT:EMAIL FORM=ID:edit_account_* ATTR=ID:account_invitations_attributes_*_email CONTENT=testemployee{{!VAR1}}@huddlehr.com
TAG POS=1 TYPE=INPUT:SUBMIT FORM=ID:edit_account_* ATTR=NAME:commit
TAG POS=1 TYPE=INPUT:SUBMIT FORM=ID:edit_account_* ATTR=NAME:commit
TAG POS=1 TYPE=A ATTR=TXT:Send<SP>Invitations<SP>To<SP>These<SP>Employees
TAG POS=1 TYPE=A ATTR=TXT:Finish<SP>Setup
TAG POS=1 TYPE=A ATTR=TXT:Finish

If I had to guess, I would say that the problem lies in my not having a background block to mimic things that would be loaded by step 2 of this form. On step 1 the background block contains a sign_up_with(email, pass). So if I am correct about the background being a reason why fill_in cannot find my form_field id names, what would I need to setup in the step2 feature spec's background block?

BTW, step 1 is a spec named create account and looks like this:

# create_account_spec.rb

require 'spec_helper'
# require 'ruby-debug'

feature 'Create Account', type: :feature do
  background do
    sign_up_with Faker::Internet.email, '1Password'
  end

  scenario 'Fill form data' do
    # visit '/setup'
    visit new_account_path
    fill_in 'First Name', with: 'Test'
    fill_in 'Last Name', with: 'Owner'
    fill_in 'Company Name', with: 'Company'
    fill_in :account_addresses_attributes_0_line_one, with: '133 Main St'
    fill_in :account_addresses_attributes_0_city, with: 'Columbia'
    select 'SC', from: 'State'
    fill_in :account_addresses_attributes_0_zip, with: '11111'
    fill_in :account_phone_numbers_attributes_0_number, with: '(111) 111-11111'
    select '(GMT-05:00) Eastern Time (US & Canada)', from: 'Time zone'
    click_button('Save & Continue')
  end
end

I've read over the following related resources to better understand Capybara and integration testing:

Undefined method `within' using capybara and rspec

Capybara's README on github

Capybara::ElementNotFound, but it is there

rspec Test Result Capybara::ElementNotFound

Capybara::ElementNotFound: Error

How to solve a Capybara::ElementNotFound Error

like image 798
sirramongabriel Avatar asked Nov 10 '22 11:11

sirramongabriel


1 Answers

Ok, so the issue as I understand it was that I did not properly setup my background to mimic the place in the site where this part2 of the multi-form's integration spec picks up. I solved this by using FactoryGirl to create a user and then used Capybara's fill_in's with user.email && user.password instead of using faker as you see above.

Here is a look at my spec as of now:

# spec/features/add_employee_spec.rb
require 'spec_helper'

feature 'Add Employee', type: :feature do 
  background do
    user = create :user
    visit user_session_path
    fill_in 'Email', with: user.email
    fill_in 'Password', with: user.password
    click_button 'Sign In'

    expect(page).to have_content('Setup An Account')
  end

  scenario 'clicks Add A New Employee and fills out the form' do
    account = create :account
    save_and_open_page
    visit setup_add_employees_path
    fill_in 'first_name', with: 'Test'
    fill_in 'Last Name', with: 'Employee'
    fill_in 'Email', with: '[email protected]'
  end
end

When using Faker to generate different usernames for a signup, I was improperly setting up the 'background' block as if I was a user looking to register for the first time.

If there is anything else I'm overlooking, or perhapse some additional tips on improving my integration specs moving forward, I look forward to your comments.

like image 131
sirramongabriel Avatar answered Nov 14 '22 23:11

sirramongabriel