0
votes

I am 'acceptance' testing creation of a Quote object with various attrs, the form is made with simple_form_for with the f.input specifying :radio_buttons. When running my tests an:

creating quote request
    Attempt to set readonly element with value: true 
     * This will raise an exception in a future version of Capybara

warning is given, suggesting that the form input has a readonly html element, which was not explicitly specified by me as true. Capybara does not seem to have an issue setting values for other input element types, therefore suggesting that they are not set as readonly.

Why is simple_form setting radio_button elements as readonly, if that is indeed what's happening here? And how do I override this so that Capybara can set these attrs with the value i place in my factory?

Code as below:

Model; quote.rb:

class Quote < ApplicationRecord
    enum industry:          [ :financial_services, :architect, :business_consultancy ]
    enum payment_frequency: [ :annually, :monthly ]
end

Controller; quotes_controller.rb:

Class QuotesController < ApplicationController


  def new
    @quote = Quote.new
  end

  def create
    @quote = Quote.new(quote_params)
    if @quote.save
        redirect_to root_url, notice: 'Quote request created'
    else
      render :new
    end
  end

  def show
    @quote = Quote.find(params[:id])
  end

private

  def quote_params
    params.require(:quote).permit(:lives_overseas)
  end
end

quote/new.html.erb

<div class='container'>
    <div class='row'>
        <div class='col-md-6'>
            <%= simple_form_for @quote do |f| %> 
                <%= f.input :lives_overseas, as: :radio_buttons %>
                <%= f.submit "Get quote", class: 'btn btn-primary' %>
            <% end %>
        </div>
    </div>
</div>

To clean up tests i refactored form completion into methods in spec/support/new_quote_form.rb:

class NewQuoteForm
    include Capybara::DSL

    def visit_page
        visit('/')
        self
    end

    def fill_in_with(params = {})
        check('GLA')                                                    # How to fetch params option if given here?
        within(".quote_prev_cover") { choose('No') }                    # How to fetch params option if given here?
        fill_in('Company name', with: params.fetch(:co_name, 'acme co'))
        fill_in('Company number', with: params.fetch(:co_number, '1234567'))
        fill_in('Postcode', with: params.fetch(:postcode, 'al1 1aa'))
        select('Financial services', from: 'Industry')                  # How to fetch params option if given here?
        within(".quote_lives_overseas") { choose('No') }                # How to fetch params option if given here?
        within("#quote_scheme_start_date_1i") { select('2018') }        # How to fetch params option if given here?
        within("#quote_scheme_start_date_2i") { select('January') }     # How to fetch params option if given here?
        within("#quote_scheme_start_date_3i") { select('1') }           
        select('Monthly', from: 'Payment frequency')                    # How to fetch params option if given here?
        fill_in('Commission level', with: params.fetch(:commission_level, '10'))
        self
    end

    def submit
        click_on('Get quote')
        self
    end
end

And the actual test which i now realise, thanks to @thomas-walpole, is the one generating the message is; create_quote_spec.rb

require 'rails_helper'
require_relative '../support/new_quote_form'

feature 'creating quote request' do
    let(:new_quote_form) { NewQuoteForm.new }

    scenario 'completing quote data' do
        new_quote_form.visit_page.fill_in_with().submit
        expect(page).to have_content('Quote request created')
    end

    scenario 'cannot reqest quote with invalid data' do
        new_quote_form.visit_page.submit
        expect(page).to have_content("Must be selected")
    end
end

Chrome inspector shows this html:

<input class="radio_buttons optional" readonly="readonly" value="false" name="quote[lives_overseas]" id="quote_lives_overseas_false" type="radio">

I've attempted to comment out config/initializers/simple_form.rb; b.optional :readonly but no change to the test warning.

1
You're getting this because your test is telling Capybara to set the values of readonly elements, if you don't want to see the error then don't try and modify readonly elements on the page. This is nothing to do with FactoryGirl and all to do with what your test is attempting to do.Thomas Walpole
Does your Quote model specify attr_readonly or override readonly_attributes ? Also, these tiny clips of files that don't actually show the code creating the errors (have_content isn't setting a readonly field on the page) make it very hard for people to help you - see stackoverflow.com/help/how-to-askThomas Walpole
Model does not explicitly specify attr_readonly or override readonly_attributes. Seems to be simple_form default setting readonly attrs to true on input specified as :radio_buttons?jbk
What is lives_overseas defined as in the DB?Thomas Walpole
Also, there is no way the spec you are showing is the one creating that output error -- have_content doesn't try to set the values of form controls, and do you really mean to be checking for the content (text) "true" on the page ???Thomas Walpole

1 Answers

1
votes

The issue is a simple_form bug setting readonly="readonly" in the false option of this radiobutton. There are two solutions, courtesy of this post.

1) Within config/initializers/simple_form_bootstrap.rb comment out b.optional :readonly within the :vertical_radio_and_checkboxes wrapper.

2) set your simple form arguments as below:

<%= f.input :prev_cover, as: :radio_buttons, collection: [['Yes', true], ['No', false]], readonly: nil %>

Though option 2 still has Capybara giving you a warning when you run your tests of; Attempt to set readonly element with value: true * This will raise an exception in a future version of Capybara