Skip to content

Instantly share code, notes, and snippets.

@kianw
Last active December 29, 2015 14:19
Show Gist options
  • Save kianw/7682977 to your computer and use it in GitHub Desktop.
Save kianw/7682977 to your computer and use it in GitHub Desktop.
Things I wish I had known before I wasted an hour figuring them out...

Models

accepts_nested_attributes_for Update Problems

If you can't update a nested object, getting a message like:

Failed to remove the existing associated parent. 
The record failed to save after its foreign key was set to nil

you're probably not permitting the nested ID parameter to be used. Check your strong parameters #permit to ensure that you're permitting the :id parameter on the nested attributes.

Views

Styles

New Stylesheets not loading

Here's an interesting one: I had a site with two different sets of stylesheets, depending on what section of the site you were in. But when you clicked a link to go from one section to another, the new page was rendered with the previous section's stylesheets. If you refreshed the page, it would render with the correct stylesheets. What gives?

Well, Turbolinks. It replaces the body tag with the linked to page's body, but doesn't mess with the head element (except to replace the title tag). So your new page renders with the old page's stylesheets. Ugh. You'd think Turbolinks would be smart enough to recognize that the head element had changed and load the entire page, but no. Thanks, guys.

JQuery

JQuery ready not working

Are you using Turbolinks? If so, don't expect Jquery ready hooks to work correctly.

Testing

RSpec

  1. You can't use subject in an around wrapper
  2. You can't use subject in a before(:all) block

FactoryGirl

Field values changing from test to test

If your factory uses a mutable object for a field value, and your test changes that object, it will instantiate new foctory instances with the changed object, not the original object. For example:

factory :something
  field1( {a: 123, b: 'hello'} )
end
a = create :something
a.field1[:a] = 456
b = create :something
b.field1[:a]

Will return 456 instead of 123!

Capybara (& Webkit)

Checkboxes and Radio Buttons

We use the iCheck JS library to override our check boxes and radio buttons. Unfortunately, this really messes with Webkit's ability to find and click these elements. In short, you can't use click_on to check or click them. Use the check_icheck_box and choose_icheck_radio methods in GeneralFeatureHelper instead.

Selecting Option

Similarly, we use the Chosen JS library to override our select tags, and Webkit doesn't like these either. Use the select_chosen_option and method in GeneralFeatureHelper.

Date Picker

Use the pick_date method in GeneralFeatureHelper to select a date from a date-picker calendar. It will navigate up to 24 months ahead to try to find the date. It currently does not navigate backwards.

Disabled / Enabled Links (Anchor Tags)

To assert that a link is disabled, check whether the :disabled attribute is non-nil. It will be non-nil (probably just an empty string) if the element is disabled, and it will be nil if the element is enabled. Asserting an element is disabled: find('#my-link-id')[:disabled].should_not be_nil Asserting an element is enabled: find('#my-link-id')[:disabled].should be_nil

element.disabled? and element['disabled'] and page.should have_selector('#my-link-id:not[disabled]') all don't seem to work correctly. Note that this applies to links, and other methods appear to work correctly for input tags and buttons.

Confirmation Dialogs

Webkit has special methods to handle confirmation dialogs and alerts. Here's sample code to first dismiss/cancel a confirmation dialog, and then accept it, and to assert the message displayed for each box. Note that the accept and dismiss commands must come before the event that triggers the dialog.

page.driver.dismiss_js_confirms!
click_on <something that triggers the dialog>
page.driver.confirm_messages.should include('Text expected on Confirmation Dialog here...')
# Now we're back on the regular page
page.driver.accept_js_confirms!
click_on <something that triggers the dialog>
page.driver.confirm_messages.should include('Text expected on Confirmation Dialog here...')
# Now we're wherever confirmation would have taken us

Record Not Found (Mongo DocumentNotFound Errors)

If you see record-not-found or Mongo DocumentNotFound errors, and you're sure you're passing the right ID parameter or whatever, it's probably because your test case is ending and the database cleaner is running before the last request is fully processed. If you're not testing anything on the page (e.g., page.should have_content...) after you visit / click / submit, Capybara will end the test case and run the database cleaner right away, even if the last request is still not finished. Testing whether database changes have been made (e.g., Employee.find(id).should...) won't cause it to wait for the request either. So -- make sure you test something on the page after the final visit / click / submit in a test case.

page.should have_content

Use have_content for text, not HTML. It will not match HTML. You might run into this if someone has put HTML tags in localized text, and then you test something like

page.should have_content( I18n.t( :my_text ) )

It won't find the content you're looking for, and your test will fail. You might be better off with something like:

page.body.should include( I18n.t( :my_text ) )

Or test something else!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment