Spreewald 1.2.0 released: new "select field should be sorted" step

Usage:

Then the "sorted" select should be sorted
But the "unsorted" select should not be sorted

How to circumvent Firefox's "Document expired" page in Selenium tests

When navigating back to a page that was received from a POST request, undesired side effects may happen. Therefore, modern browsers try to keep users from doing so, i.e. Firefox 24 displays an error page explaining what's wrong. If the user presses "Try Again", it shows an additional alert asking whether the user is certain.

Solution

If you need to circumvent this protection, e.g. to test that your application behaves correctly despite being misused, do this:

page.execute_script 'history.back()'
page.execute_script 'retryThis(this)...

Cucumber: More patience for Selenium features

When running Selenium features with parallel_tests, some browser-server interaction might take longer than usual and the impatient Capybara will not wait enough to see results.

Put the attached file into features/support/ to make Capybara more patient in scenarios tagged @javascript.

How to upgrade Cucumber on Rails 3+

  1. Run bundle update cucumber capybara cucumber-rails to update to the newest versions.

  2. Backup your features/support/path.rb to be able to add your own paths again after the cucumber installation script in step 4.

  3. Backup your features/support/env.rb file to be able to reintegrate parts like your blueprints setup:

    ENV["RAILS_ENV"] ||= "cucumber"
    require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')
    require 'spec/support/blueprints'
    
  4. Run `$ rails generate cucumber:install --capyba...

Getter and setter functions for JavaScript properties

JavaScript objects can have getter and setter functions that are called when a property is read from or written to.

For example, if you'd like an object that has a virtual person.fullName attribute that dynamically composes person.firstName and person.lastName:

var person = {

  firstName: 'Guybrush',

  lastName: 'Threepwood',

  get fullName() {
    return this.firstName + " " + this.lastName;
  },
  
  set fullName(name) {
    var parts = name.split(" ");
    this.firstName = parts[0];
    this.lastName = parts[1];
  }

};
`...

Testing focus/blur events with Cucumber

This is a problem when using Selenium with Firefox. We recommend using ChromeDriver for your Selenium tests.


This setup allows to test focus/blur events in Cucumber tests (using Selenium). For background information, see How to solve Selenium focus issues.

Cucumber step definition:

# This step is needed because in Selenium tests, blur events are not triggered
# when the browser has no focus.
When /^I unfocus the "(.*?)" field to trigger ja...

Taking screenshots in Capybara

Capybara-screenshot can automatically save screenshots and the HTML for failed Capybara tests in Cucumber, RSpec or Minitest.

Requires Capybara-Webkit, Selenium or poltergeist for making screenshots. Screenshots are saved into $APPLICATION_ROOT/tmp/capybara.

Manually saving a page

Additionally you can trigger the same behavior manually from the test using Capybara::Session#save_and_open_page and [...

Reading an element's attributes with Capybara

capybara_element['attribute_name'] allows accessing an element's attributes in Capybara.

A few examples:

find('#my_element')['class']
# => "first-class second-class"

find('#my_input')['placeholder']
# => "My placeholder value"

find('a#example-link')['href']
# => "http://example.com"

find('#my_element')['missing_attribute']
# => nil

Cucumber: Removing uploaded files after test runs

Cucumber will clean up files you've uploaded in your Cucumber features automatically with the attached code. Put the file in features/support/.

Cucumber step to test whether a select field is sorted

This step will pass if the specified select is sorted.

Then /^the "(.*?)" select should be sorted$/ do |label, negate|
  select = find_field(label)
  options = select.all('option').reject { |o| o.value.nil? }

  options.collect(&:text).each_cons(2) do |a,b|
    (a.text.downcase <=> b.text.downcase).should <= 0
  end
end

In conjunction with this custom matcher, the each_cons block can be replaced with:

options.should be_naturally_sorted

Usage

Then the "Organizations" select should be sorted...

Asset Pipeline Basics

The Rails asset pipeline improves delivery of application assets (javascripts, stylesheets, images, fonts). Here are some basic facts about its inner workings.

No magic

Manifests are the handle on your assets:

app/assets/stylesheets/application.css # use via: stylesheet_link_tag 'application'

The asset pipeline only considers files you explicitly require within your manifest files. The most common directives used in manifests are require some/file and require_tree some/directory. Paths may be **relative to the current director...

vague puppet error messages with broken yaml files

If you get one of this errors:

Error: Could not retrieve catalog from remote server: Error 400 on SERVER: (<unknown>): found character that cannot start any token while scanning for the next token at line 1297 column 3
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run

Error: Could not retrieve catalog from remote server: Error 400 on SERVER: undefined method `empty?' for nil:NilClass at /etc/puppet/environments/production/manifests/nodes.pp:1 on node example.makandra.de
Warning: ...

How to: Context-dependent word expansion in RubyMine

One of the many useful features of TextMate is autocompletion of words. If I were in TextMate right now, I could write "au[tab]", and it would complete it to "autocompletion". RubyMine can do this, too. When you write a word (e.g. a variable name), just hit ALT + / repeatedly and it will offer all completions for the letters you typed. This action is called Cyclic Expand Word in RubyMine / IntelliJ IDEA.

This feature keeps you from mistyping variable names, saves you keystrokes and speeds up development. ~10 keystrokes to the price ...

How to combine "change", "up", and "down" in a Rails migration

Rails migrations allow you to use a change method whose calls are automatically inverted for the down path. However, if you need to some path-specific logic (like SQL UPDATE statements) you can not define up and down methods at the same time.

If you were to define define all 3 of them, Rails would only run change and ignore up and down. However, Rails 4+ features a helper method called reversible:

class MyMigration < ActiveRecord::Migration

  def cha...

Upgrading a Rails 3.2 application to Ruby 2.1 is really easy

Upgrading from Ruby 1.8.7 to 2.1.2 took me an hour for a medium-sized application. It involved hardly any changes except

  • removing the occasional monkey patch where I had backported functionality from modern Rubies
  • Migrating from require to require_relative where I loaded RSpec factories in Cucumber's env.rb (the Rails application root is no longer in the load path by default)
  • replacing the old debugger with byebug
  • removing sytem_timer from Gemfile (see [this SO thread](http://stackoverflow.com/questions/7850216/how-to-inst...

Cucumber features as documentation

Cucumber allows for prose in features and scenarios. Example:

Feature: Cancel account

  There are several ways to cancel a user account. Admins need to 
  do it in complex cases, but normally, users can do it themselves.
  
  Scenario: User cancels his own account
    
    Users should be able to cancel an account themselves, so the 
    admins do not need to do it.
    
    Given a user account for "willy@astor.de"
    When I sign in as "willy@astor.de"
    And I follow "Cancel account"
    Then I should see "Account canceled"...

Firefox: Focus-sensitive Selenium tests do not work reliably in parallel test execution

This is a problem when using Selenium with Firefox. We recommend using ChromeDriver for your Selenium tests.


Firefox will not trigger focus/blur events when its window is not focused. While this makes sense in standard usage, it breaks in parallel test execution.

Please do not rely on focus events in your tests. The linked card has an example of how to build passing tests that deal with focus/blur events.

MetricsGraphics.js

MetricsGraphics.js is a library built on top of D3 that is optimized for visualizing and laying out time-series data. It provides a simple way to produce common types of graphics in a principled, consistent and responsive way. The library currently supports line charts, scatterplots and histograms as well as features like rug plots and basic linear regression.

New Firefox and gem versions for our Selenium testing environment (Ubuntu 14.04+)

Firefox 5.0.1, which we were using for most Rails 2.3 projects, does not run on Ubuntu 14.04 any more. Here is how to update affected projects.

  1. Update (or create) .firefox-version with the content: 24.0
    If you haven't installed Firefox 24 yet, the next time you run tests with Geordi, it will tell you how to install it.

  2. On a Rails 2 project:

Heads up: JavaScript does not like big numbers

In a JavaScript console, type this:

> 9112347935156469760
9112347935156470000

Ooops. And that's not a float!

This occurs because JavaScript uses double precision floats to store numbers.

So according to IEEE floating point definition only numbers between -(2^53 - 1) (-9007199254740991) and 2^53 - 1 (9007199254740991) can safely be represented in JavaScript.

Note that ECMAScript 6 will probably also offer [Number.MAX_SAFE_INTEGER](https://developer.mozilla.org/en-US/docs/W...

HTML5: Allow to choose multiple files with a vanilla file picker

Modern browsers natively suppport file pickers that allow the user to choose multiple files at once. To activate this feature, set the multiple attribute:

<input type="file" name="images[]" multiple />

Or in a Rails view:

<%= file_field_tag "images[]", multiple: true %>

This works in IE10+.

Make sure that the field name ends in [] so your server-side code will parse the incoming files into an array. Obviously this naming convention is not compatible with default Rails nested attribute setters, so you'll need to write a form ...

How to fix: Font too small when reading e-mails in Thunderbird

In Thunderbird, you can set custom font faces and sizes for reading plain-text e-mails. However, Thunderbird sometimes "randomly" does not respect your choices.

This is actually not a bug, but a rather weird feature: Fonts are defined per encoding of e-mails.

Some e-mails will be considered Unicode, some Western (ISO 8859-1), and some maybe yet another encoding.

The advanced font settings dialog by default just opens on "Western". Choose a different encoding from the "Fonts for" dropdown menu and you'll see that your custom font sett...

Capybara will not find links without an href attribute

Capybara will fail to find <a> tags that are missing an href attribute. This will probably happen to you every now and then on JavaScript-heavy applications.

An example would be an AngularJS application where the following HTML actually works. [1]

<a ng-click="hello()">Hello</a>

Capybara will fail to find that link, even though looking it up via the DOM shows it:

>> find_link("Hello")
Capybara::ElementNotFound: Unable to find link "Hello"

>> find("a").text
=> "Hello"

To make find_link and click_link work, ...

The Curious Case of the Flip-Flop

The flip-flop operator is a hotly contested feature of Ruby. It's still struggling to find an idiomatic use case, except for a few very rarely needed things. It's not something you'll likely reach for on a daily, weekly or even monthly basis. The only thing you really need to know about it is what it does, and that's only in case you encounter it in someone else's code. Many even go as far to say not to use the flip-flop operator, that it only adds confusion.

My brain just melted.