Giter Club home page Giter Club logo

formulaic's Introduction

Formulaic

Build Status Code Climate

Remove the tedium of formulaic form filling with Capybara.

Formulaic allows you to specify a hash of attributes to be input rather than procedurally calling Capybara’s DSL methods.

Usage

  gem 'formulaic', group: :test
feature 'New user registration' do
  scenario 'successfull sign up' do
    visit sign_in_path

    fill_form(:user, { name: 'Caleb', email: '[email protected]', 'Terms of Service' => true })
    click_on submit(:user)

    expect(page).to have_content t('user.create.success')
  end
end

fill_form

fill_form(model_name, :new, attributes)

fill_form provides an interface to completely filling out a form. Provide the model_name as a symbol and attributes as a hash of column name => database value or label string => database value.

If an attributes key is a String, it will be used as the literal label. For Symbol we will attempt to translate, fall back to human_attribute_name if available, then call to_s.

input

input(model_name, field)

input gives an easy way to find the translated text of an input. It is primarily used internally to fill <input>s, but is provided in the public API as it could be useful.

submit

submit(model_name, :create)

submit functions like input, but finds the translation for the submit button of the form. model_name should be the same as what you provide to fill_form. Typically, the return value of submit will be passed directly to Capybara’s click_on method.

If you are submitting a form that is not for the create action, you may need to pass the action:

submit(:user, :update)

The model_name and action should match up to the helpers.submit.<model_name>.<action> translations.

fill_form_and_submit

fill_form_and_submit(:user, :new, attributes)

Effectively a fill_form followed by click_on submit, but smart enough to fill_form with :new and submit with :create and the edit/update cousin.

Nested Forms

If you have nested forms, through fields_for (or any variant), you are able to fill them with an extra call to fill_form.

fill_form(main_model_name, main_model_attributes)
fill_form(nested_model_name, nested_model_attributes)

Integration with RSpec:

# spec/spec_helper.rb

RSpec.configure do |config|
  config.include Formulaic::Dsl, type: :feature
end

Integration with Minitest or Test::Unit:

# test/test_helper.rb

class ActionDispatch::IntegrationTest
  include Capybara::DSL
  include Formulaic::Dsl
end

Integration with Factory Bot

fill_form(:user, attributes_for(:user))

You may have attributes included in your User factory that don’t pertain to sign up:

fill_form(:user, attributes_for(:user).slice(*sign_up_attributes))

# ...
def sign_up_attributes
  [:name, :email, :terms_of_service]
end

Integration with Capybara::TestHelper

class BaseTestHelper < Capybara::TestHelper
  include Formulaic::Dsl
end

or alternatively delegate the needed methods:

class FormTestHelper < BaseTestHelper
  delegate_to_test_context(:fill_form, :input, :submit, :fill_form_and_submit)
end

Assumptions

Formulaic relies pretty heavily on the assumption that your application is using translations for SimpleForm and input helpers, using the simple_form.labels.<model>.<attribute> and helpers.submit.<model>.<action> conventions.

You can still use Formulaic by using strings as keys instead of symbols, which it knows to pass directly to fill_in rather than trying to find a translation. You’ll need to find submit buttons yourself since submit is a thin wrapper around I18n.t.

Formulaic assumes your forms don't use AJAX, setting the wait time to 0. This can be configured using:

Formulaic.default_wait_time = 5

Known Limitations

  • Formulaic currently supports the following mappings from the #class of the attribute values to Capybara method calls:

    Classes Formulaic’s action
    String fill_in, choose, or select
    Date, ActiveSupport::TimeWithZone select year, month, and day
    TrueClass check
    FalseClass uncheck
    Array check or select each array member, which should all be strings. If not all items can be selected or checked, an error will be thrown.
    File attach_file with File#path
  • Formulaic is currently tied to simple_form translations and field structure. If you pass a string for the attribute, we’ll try to fill the input that relates to that label. We would be happy to work with you to add support for other form builders.

  • Formulaic currently does not support forms with duplicate labels, as it is designed to be as similar as possible to a user completing a form—it looks at the labels to determine where to fill what data.

  • Formulaic can’t figure out how to fill fields with HTML labels: page.fill_in('<strong>Text</strong> here', with: 'something') doesn’t work with Capybara. The usual workaround is to pass a CSS selector (which you can do by passing a string as the attribute key).

  • Formulaic can't handle multiple file attachments on the same input.

About

Formulaic is maintained by Caleb Hearth and formerly thoughtbot with the help of community contributors. Thank you!

formulaic's People

Contributors

acrogenesis avatar alex-ross avatar calebhearth avatar craigwilliams avatar croaky avatar djcp avatar ecbypi avatar elmassimo avatar gregmolnar avatar hovsater avatar ilkhamgaysin avatar jessieay avatar mcmire avatar mike-burns avatar petergoldstein avatar rossta avatar seanpdoyle avatar sfroehler avatar tysongach avatar zamith avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

formulaic's Issues

Update CI

Move to another CI - GitHub maybe? - and update the metrix for currently supported Rubies and Railses

Rails SimpleForm I18n Formulaic::InputNotFound

Example:

We have simple form for user with email field

f.input :email

and we have simple_form.en.yml

labels:
      user:
        new:
          email: 'Enter your email address'

when we try to fill in form like here

fill_form(
  :user,
  email: email,
  password: password
)

then we get error

Formulaic::InputNotFound:
       Unable to find input "Email".

so we have to do like here

fill_form(
  :user,
  'Enter your email address' => email,
  password: password
)

Add an optional syntax for better FactoryGirl support

When I type fill_form(:user), that should function as fill_form(:user, attributes_for(:user)) currently does.

When I type fill_form(:user, :name, :email), that should function the same as fill_form(:user, attributes_for(:user).slice(:name, :email)) currently does.

When I type fill_form(:user, :name, password: 'password'), that should function the same as fill_form(:user, attributes_for(:user).slice(:name).merge(password: 'password')) currently does.

Instructions for Capybara Test Helpers

Hi there!

I wanted to ask if you would be willing to accept a pull request to add instructions on how to setup formulaic when using Capybara Test Helpers.

It would be a quick snippet:

# test_helpers/base_test_helper.rb
class BaseTestHelper < Capybara::TestHelper
  include Formulaic::Dsl
end

or alternatively delegating the needed methods:

# test_helpers/base_test_helper.rb
class BaseTestHelper < Capybara::TestHelper
  delegate_to_test_context(:fill_form, :input, :submit, :fill_form_and_submit)
end

Cheers!

Support of accepting object instead passing symbol of type of object

For example we have

fill_form(:user, user_attributes)

and this is used in one spec file.

Lets image we have two or three registration forms through devise or any other authentication plugins and in our system we have two registrable resources for example admins and users or three admins, users, members.

So then instead writing this line

fill_form(:user/:admin/:member, user/admin/member_attributes)

in each scenario for per resource I want to declare it once on my shared_example(https://www.relishapp.com/rspec/rspec-core/docs/example-groups/shared-examples) file for example

fill_form(resource, resource_attributes)

By standard way for this purposes I need to create

let(:resource_name) { admin/member/user.class.name.downcase.to_sym }

and pass it to this

fill_form(resource_name, resource_attributes)

Is it possible to add this or it's overhead?

Uses deprecated Fixnum constant

The Fixnum constant is deprecated in Ruby 2.4, to be replaced with Integer. This causes a warning to be printed:

/home/mike/.gem/ruby/2.4.0/gems/formulaic-0.3.0/lib/formulaic/form.rb:11: warning: constant ::Fixnum is deprecated

Let's find a way to silence that warning.

Filling in dropdown is very slow

I had following in my spec:

factory :business_details do
  name      Forgery(:name).company_name
  phone     Forgery(:address).phone
  country   Forgery(:address).country
  state     Forgery(:address).state
  city      Forgery(:address).city
  zip       Forgery(:address).zip
  address_1 Forgery(:address).street_address
end
fill_form :business_details, attributes_for(:business_details)

It was taking ~10 seconds.
All fields are string inputs except 1 country dropdown.
After refactoring to:

fill_form :business_details, attributes_for(:business_details).except(:country)
select attributes_for(:business_details)[:country], from: 'Country'

It took less than 1 second.

Better error messages when an input can't be found

I love the way formulaic makes my specs read when everything is working, but when I use its DSL and I'm missing some translations or I don't have the parameters quite right, it can be frustrating to figure out why. I find myself source diving formulaic to reverse engineer what went wrong.

I wonder if the InputNotFound error could be improved to return a list of inputs that were found?

Reliance on human_attribute_name does not work with plural model classes

I have an ActiveModel class named Credentials with encapsulates an email and password form. I define the following translations:

---
en:
  activemodel:
    attributes:
      credentials:
        email: Email Address
        password: Password

However, when I call fill_form(:credentials, { email: '[email protected]', password: 'password' }, I get an InputNotFound error. Formulaic first tries to use simple form translations to find the input. Failing that, it tries to get at human attribute name by classifying the model name passed to fill_form. Unfortunately, classify uses the inflector to singularize the input.

I don't know if there's a great solution to this. I can't think of a scenario where the singularization would be useful for formulaic, but I also think reimplementing classify might be more trouble than its worth here as well.

For now, I can work around this by duplicating the translations as simple_form label translations, but this is also not an ideal solution.

Capybara/Formulaic doesn't find input as: :radio_button

I have an simple_form input that maps to a string attribute, since I want the user to select from fixed options I'm using it as radio_buttons:

<%= s.input :sex, collection: [['M','Male'] ,['F', 'Female']], as: :radio_buttons, label_method: :last, value_method: :first, item_wrapper_class: 'inline', checked: true %>

In my features I have:

fill_form(:student, { name: 'Joe', sex: 'M' })

But capybara isnt beeing able to find it (actually formulaic is not finding it):

 **Formulaic::InputNotFound:**
   Unable to find input "Sex".

The only way it found it was hard referencing it:


        fill_form(:student, {
            name: 'Joe',
            'enrollment[student_attributes][sex]' => 'M'
        })

Integration with Cucumber?

I tried using formulaic in my Cucumber steps:
fill_form(:resume, FactoryGirl.attributes_for(:resume))

Getting
undefined method `fill_form' for #Cucumber::Rails::World:0x007f8351584630 (NoMethodError)

Is Cucumber supported at all? If not, will it be supported?

Formulaic does not know how to fill in a Symbol value

Hi,

I'm using Formulaic in a project of mine and we use an enum type for selecting a user's role. Since enum values are of type Symbol, Formulaic complains with the following error message:

Formulaic does not know how to fill in a Symbol value

My suggestion would be to convert symbol values to strings by calling #to_s on them and then let StringInput class handle it as usual. What do you think about this? Can this have any side effects that I'm not seeing right now?

I'd love to send a pull request as we decide on a solution! 😄

Cheers,
Kevin

Does not support multiple capybara sessions

We inherited the experience pattern from thoughtbot NYC. It is pretty fantastic.

We made a small modification in some of the experiences so we can handle multiple sessions.

class StudentExperience < Experience
  def page
    @page || begin
      Capybara.using_session(:student) do
        @page = Capybara.current_session
      end
    end
  end
end

This would allow this specific experience to have it's own session so we could go back and form between two different roles without having to use Capybara.using_session

However by default formulaic uses Capybara.current_session so if we were to use fill_form inside an experience it breaks because it looks at the wrong session.

I am willing to put in the work make formulaic work with this pattern but I need some guidance in how you wish this to be coded. Specifically do you want this passed down be default in the DSL#fill_form then in the Input just execute all actions off the passed down session?

It seems like a smell to pass the session all the way down but I can't figure out a better way to do it.

submit() isn't a method

The README says to do click_on submit(:user), but submit isn't a public method (and looks like it may not be a method at all?).

What's the recommended way to submit a form?

Master branch specs are failing with I18n::InvalidLocale

When I run the specs locally I get one failure:

Failures:

  1) Fill in user form finds and fills a spanish locale date field
     Failure/Error: I18n.locale = :es
     I18n::InvalidLocale:
       :es is not a valid locale
     # ./spec/features/fill_in_user_form_spec.rb:88:in `block (2 levels) in <top (required)>'

Master passed 'about a month ago' on Travis, so I assume a gem release since then has caused this breakage. I can't the inspect the Gemfile.lock created by the CI build to compare against my local version, so I'm not sure how to track down the cause of this.

Uninitialized Constant Formulaic (NameError)

Hi, I am trying to integrate Formulaic into my RSpec test suite. But whenever I include the config.include Formulaic::Dsl, type: :feature line in the spec_helper.rb, I am getting the following error.

I am running on Rails 4.2.5.2 and the Formulaic version in 0.3.0. I tried the same with another app running on 4.2.5. It's been the same. It would be really great if someone can point what I am doing wrong.

Thank You.

Here is the trace.

/home/p150/Documents/code/booker/spec/spec_helper.rb:18:in `<top (required)>': uninitialized constant Formulaic (NameError)
    from /home/p150/.rbenv/versions/2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /home/p150/.rbenv/versions/2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /home/p150/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.3/lib/rspec/core/configuration.rb:1295:in `block in requires='
    from /home/p150/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.3/lib/rspec/core/configuration.rb:1295:in `each'
    from /home/p150/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.3/lib/rspec/core/configuration.rb:1295:in `requires='
    from /home/p150/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.3/lib/rspec/core/configuration_options.rb:109:in `block in process_options_into'
    from /home/p150/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.3/lib/rspec/core/configuration_options.rb:108:in `each'
    from /home/p150/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.3/lib/rspec/core/configuration_options.rb:108:in `process_options_into'
    from /home/p150/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.3/lib/rspec/core/configuration_options.rb:21:in `configure'
    from /home/p150/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.3/lib/rspec/core/runner.rb:105:in `setup'
    from /home/p150/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.3/lib/rspec/core/runner.rb:92:in `run'
    from /home/p150/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.3/lib/rspec/core/runner.rb:78:in `run'
    from /home/p150/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.3/lib/rspec/core/runner.rb:45:in `invoke'
    from /home/p150/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.3/exe/rspec:4:in `<top (required)>'
    from /home/p150/.rbenv/versions/2.3.0/bin/rspec:22:in `load'
    from /home/p150/.rbenv/versions/2.3.0/bin/rspec:22:in `<main>'

Uninitialized Constant when calling `fill_form`

If I call fill_form with a form name that does not appear on the page, or a field that does not appear on the page, formulaic errors with:

NameError: uninitialized constant Formulaic::InputNotFound

Capybara deprecation errors

Starting with a recent capybara release, using formulaic kicks out deprecation warnings. Example from the formulaic feature spec:

Locator #<Formulaic::Label:0x007fc83c29c4b0 @model_name=:user, @attribute=:name, @action=:new> must be an instance of String or Symbol. This will raise an error in a future version of Capybara.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.