0
votes

I am trying to test the following form which allows a user to hide their profile by checking a checkbox.

<%= form_tag toggle_hidden_path, id: 'toggle-form', method: :put, remote: true do %>
  <%= check_box_tag(:hide, value = '1', checked = @account_is_hidden) %>
<% end %>

When checked or unchecked (changed), the form is submitted using JS.

<script type="text/javascript">
  $('#hide').on('change', function() { $(this.form).submit(); });
</script>

My controller action and method within the model toggle the :hidden boolean.

  # accountsController

  def toggle_hidden
    @account = current_user.account
    @account.toggle_hidden!
  end

  # account.rb

  def toggle_hidden!
   toggle!(:hidden)
  end

I am using Rspec and capybara. My test is below

require 'rails_helper'

feature 'Hide and show profile' do
  let(:account) {create :account}

  scenario 'successfully', js: true do
    login_as(account.user)
    visit dashboard_path

    expect(account.hidden).to eq(false)

    expect(page).to have_field('hide')
    check('hide')
    expect(page).to have_field('hide', checked: true)

    expect(account.hidden).to eq(true)
  end
end

The test error;

Failures:

1) Hide and show profile successfully
 Failure/Error: expect(account.hidden).to eq(true)

   expected: true
        got: false

   (compared using ==)

Any help is greatly appreciated as to why this may not be working..

EDIT

I added a flash notice to display when the checkbox is checked/unchecked.

  def toggle_hidden
   @account = current_user.account
   @account.toggle_hidden!
    respond_to do |format|
     format.js { flash[:notice] = "Hidden toggled" }
    end
  end

and updated the spec - but still, test does not pass.

expect(page).to have_content('Hidden toggled')
1

1 Answers

0
votes

You have already loaded account so the value of hidden in the object won't change. In order to see the new value you'd need to reload the object

expect(account.reload.hidden).to eq(true)

However, since actions (check/uncheck/click/etc) aren't guaranteed to wait for any behaviors triggered by them it's highly likely the form submission won't have completed (and hence the object not been updated) by the time your expectation runs (hence why expectations on database objects are generally frowned upon in feature specs). If your page has a visible change when the form submit is completed you should set an expectation on that before checking the database object, or better yet just skip testing the database object and instead test what the user can actually see - that their profile is hidden after they've checked the box.