Inspect the page content in a Cucumber session

When you need to see the content of a page (i.e. not all the HTML but the relevant text body)

  • you can do pp (html_content)
    • pp will format the html String human readable pretty printed
  • where html_content can be replaced by one of the following commands:

Rails

body or response.body

Capybara:

  • page.driver.html.content
  • page.body

Webrat:

Nokogiri::HTML(response.body).content

The returned strings can be cleaned up by calling .gsub(/^\s*$/, '').squeeze("\n") on them.\
Although this may be useful for d...

Check if a field or button is disabled with Cucumber

Using this step definition you can check if any form field (text field, checkbox, etc) or button is disabled:

Then the "Name" field should be disabled
  And the "Save" button should be disabled
But the "Locked" field should not be disabled

Capybara

This step part of Spreewald.

Webrat

Then /^"([^\"]*)" should( not)? be disabled$/ do |label, negate|
  attributes = field_labeled(label).element.attributes.keys
  attributes.send(negate ? :should_not : :should...

Test that an exception or error page is raised in Capybara

You can use these step definitions:

Then /^I should not see an error$/ do
  (200 .. 399).should include(page.status_code)
end

Then /^I should see an error$/ do
  (400 .. 599).should include(page.status_code)
end

Note that you need to tag the scenario with @allow-rescue to test that an error is shown like this

@allow-rescue
Scenario: Accessing the admin area requires a login
  When I go to the admin area
  Then I should see an error

These step definitions will not work for @javascript scena...

Ruby 2.0 Refinements in Practice

The first thing you need to understand is that the purpose of refinements in Ruby 2.0 is to make monkey-patching safer. Specifically, the goal is to make it possible to extend core classes, but to limit the effect of those extensions to a particular area of code. Since the purpose of this feature is make monkey-patching safer, let’s take a look at a dangerous case of monkey-patching and see how this new feature would improve the situation.

Install RubyMine under Ubuntu

This card explains how to install RubyMine for the first time. If you want to upgrade an existing RubyMine installation (after legacy install) to a newer version, see How to upgrade RubyMine.


Option A (new way)

Ubuntu 16.04 comes with snap, a way to package software with all its dependencies. RubyMine is also packaged as a snap.

A snap will always track a channel (like stable, beta) and automatically update to the newest version available in this channel. By default the snap daemon will check for ...

Disable automatic e-mail checking in Thunderbird 3

Have you guys ever done the math on that? You asked or allowed for 24000 interruptions from literally every human being in the world who could fall onto a keyboard and make an e-mail go to you. (Merlin Mann)

So you decided to put a price on your attention and not check your e-mail 24000 times a year. A first step is to disable automatic e-mail checks in Thunderbird.

  1. Open Edit -> Account settings and select your incoming mail account.
    ...

Manipulate an array attribute using multiple check boxes

E.g. when you're using a tagging gem, you have seen virtual attributes that get and set a string array:

post = Post.last
puts post.tag_list # ['foo', 'bar', 'baz']
post.tag_list = ['bam']
puts post.tag_list # ['bam']

If you would like to create a form displaying one check box per tag, you can do this:

- form_for @post do |form|
  = form.check_box :tag_list, { :multiple => true }, 'foo', nil
  = form.check_box :tag_list, { :multiple => true }, 'bar', nil
  =...

Use the back button in Cucumber

In order to go back one page in your Cucumber tests, you can use the following step definition for Capybara:

When(/^I go back$/) do
  visit page.driver.request.env['HTTP_REFERER']
end

If you're on Webrat, this should work:

When(/^I go back$/) do
  visit request.env["HTTP_REFERER"])
end

An improved version of this step is now part of our gem spreewald on Github.

Thoughtbot's experiences with headless Javascript testing

Selenium has been the siren song that continually calls out to us. Unfortunately, in practice we’ve been unable to get Selenium to run reliably for real applications, on both developers machines and on the continuous integration server. This failure with Selenium has caused us to search for alternative solutions

Test that a select option is selected with Cucumber

This step tests whether a given select option comes preselected in the HTML. There is another step to test that an option is available at all.

Capybara

Then /^"([^"]*)" should be selected for "([^"]*)"(?: within "([^\"]*)")?$/ do |value, field, selector|
  with_scope(selector) do
    field_labeled(field).find(:xpath, ".//option[@selected = 'selected'][text() = '#{value}']").should be_present
  end
end

Webrat
...

Migrate or revert only some migrations

To only run the next two migrations:

rake db:migrate STEP=2

To revert the previous two migrations:

rake db:rollback STEP=2

To revert the last two migrations and then migrate to the most current version:

rake db:migrate:redo STEP=2

To migrate to a given migration number, regardless of whether that means migrating up or down:

rake db:migrate VERSION=20100627185630

To migrate exactly one individual migration out of the sequence* (careful):

rake db:migrate:up VERSION=20100627185630

To revert exactly one individual m...

Prevent Bundler from downloading the internet

As a user of Bundler you have spent significant time looking at this message:

Fetching source index for http://rubygems.org/

To make Bundler skip this index update and only use installed gems, you can use the --local option:

bundle install --local

Unfortunately this does not work with bundle update.

It is said that Bundler 1.1 will use a feature of Rubygems.org that allows partial index updates. Hopefully the wh...

Test that a CSS selector is present with Cucumber

This note describes a Cucumber step definition that lets you test whether or not a CSS selector is present on the site:

Then I should see an element "#sign_in"
But I should not see an element "#sign_out"

Here is the step definition for Capybara:

Then /^I should (not )?see an element "([^"]*)"$/ do |negate, selector|
  expectation = negate ? :should_not : :should
  page.send(expectation, have_css(selector))
end

Here is the step definition for Webrat:

Then /^I should (not )?see an element "([^"]*)"$/ do |negate...

Terminus: a client-side Capybara driver

Terminus is a Capybara driver where most of the driver functions are implemented in client-side JavaScript. It lets you script any browser on any machine using the Capybara API, without any browser plugins or extensions.

Standalone Cucumber Test Suite

Sometimes you inherit a non Rails or non Rack based web app such as PHP, Perl, Java / JEE, etc. I like using cucumber for functional testing so I put together this project structure to use as a starting point for testing non Ruby web based applications.

Getting your e-mails back after upgrading Thunderbird to version 3

If you previously used version 2.x of Thunderbird and upgraded to 3.x (for example through an Ubuntu release upgrade) you might notice that Thunderbird will not show any of your old e-mails or settings.

This results from a different directory being used for storing profiles and configuration.

You can replace the blank profile with your old one like this:
cd ~
mv .thunderbird .thunderbird-invalid
cp -R .mozilla-thunderbird .thunderbird

Upon its next start, Thunderbird brings up the migration wizard introducing you to a few vers...

Match strings in a given order with Cucumber and Capybara

Sometimes the order in which strings appear on a page matters to you.

Spreewald gives you steps like these:

Then I should see in this order:
  | Alpha Group |
  | Augsburg    |
  | Berlin      |
  | Beta Group  |

Or, if you prefer multiline strings:

Then I should see in this order:
  """
  Alpha Group
  Augsburg
  Berlin
  Beta Group
  """

The step ignores all HTML tags and only tests on plain text.

Machinist: Refer to another named blueprint inside a blueprint

Note: We are talking about Machinist 1 here, Machinist 2 may have solved this or might require a different approach.


Machinist allows named blueprints (e.g. User.blueprint(:admin)) that inherit from the master blueprint (User.blueprint).

If you also want to inherit from another blueprint (e.g. if "vip" should load "premium" and the master blueprint) you can do this:
User.blueprint(:vip) do
# Fields for the vip blueprint go her...

Using the full power of have_css

Capybara's has_css? matcher has a couple of options you might find useful.

Check that a selector appears a given number of times

Use the :count option like this:

Then /^I should see (\d+) users?$/ do |count|
  page.should have_css('ul#users li', :count => count.to_i)
end

Check that a selector has a given text content

Use the :text option like this:

Then /^I should see a user with name "([^\"]*)"$/ do |nam...

An obscure kernel feature to get more info about dying processes

This post will describe how I stumbled upon a code path in the Linux kernel which allows external programs to be launched when a core dump is about to happen. I provide a link to a short and ugly Ruby script which captures a faulting process, runs gdb to get a backtrace (and other information), captures the core dump, and then generates a notification email.

Cucumber step to match table rows with Capybara

These steps are now part of Spreewald.

This note describes a Cucumber step that lets you write this:

Then I should see a table with the following rows:
  | Bruce Wayne       | Employee    | 1972 |
  | Harleen Quinzel   | HR          | 1982 |
  | Alfred Pennyworth | Engineering | 1943 |

If there are additional columns or rows in the table that are not explicitely expected, the step won't complain. It does however expect the rows to be ordered as stat...

Reload the page in your Cucumber features

Both these approaches will keep your GET parameters -- and will only work for GET requests.

  • Capybara:

    When /^I reload the page$/ do
      visit [ current_path, page.driver.request.env['QUERY_STRING'] ].reject(&:blank?).join('?')
    end
    
  • Webrat:

    When /^I reload the page$/ do
      visit url_for(request.params)
    end
    

For a step that distinguishes between drivers (Selenium, Rack::Test, Culerity), check [n4k3d.com](http://n4k3d.com/blog/2011/02/02/reloading-the-page-in-cucumber-with-capybara-and-seleniu...

Replace substrings in Cucumber step argument transforms

Cucumber step argument transforms can be a powerful way to make your steps more flexible.

Note however that if your transform only matches a substring (no ^ and $ markers at the beginning and end), you are still expected to return a replacement for the whole string that was piped through the transform. If you don't do that, you will truncate that string and possibly make the calling step match where it should not.

Let's say you want a transform that replaces subs...

RSpec's context method is broken

RSpec's context (which is basically an alias for describe) takes over your whole application. No object may have its own context method, or you will always receive errors like

"No description supplied for example group declared on ~/project/app/..."

The easiest workarounds:

  • do not name any method context
  • use describe instead of context in your specs, and put this into your spec_helper.rb:\
    Spec::DSL::Main.class_eval do
    if method_defined? :context
    undef :context
    end
    end