Jasmine: Testing complex types for equality

Jasmine comes with two matchers that test for equality. The first is toBe:

expect(first).toBe(second)

toBe passes when first === second. Unfortunately this is useless for non-primitive values because JavaScript is a horrible language.

However, Jasmine comes with another matcher toEqual:

expect(first).toEqual(second)

This matcher behaves as a human would expect for types like the following:

  • Arrays
  • Objects
  • Nested array/object constructs
  • Regular expressions...

Testing regular expressions visually

Developing complex regular expressions quickly blows my mind. Here are some online regex editors that help you by highlighting matching text and capture groups:

Manually trigger a delegated DOM event

When you register a delegated event using on (or the deprecated delegate / live), it is somewhat hard to manually trigger these events manually, e.g. for testing.

After trying jQuery's trigger to no avail, I had success by using native Javascript methods to create and dispatch an event. For instance, to trigger a mousedown event:

element = $('...').get(0);
event = new MouseEvent('mousedown', { view: window, cancelable: true, bubbles: true }...

Show details of TLS/SSL connections of remote hosts

sslscan is a nice tool to show details about TLS/SSL connections:

~> sslscan some-host-at.makandra.de

Testing SSL server some-host-at.makandra.de on port 443

  Supported Server Cipher(s):
    Failed    SSLv3  256 bits  ECDHE-RSA-AES256-GCM-SHA384
    Failed    SSLv3  256 bits  ECDHE-ECDSA-AES256-GCM-SHA384
    Failed    SSLv3  256 bits  ECDHE-RSA-AES256-SHA384
    Failed    SSLv3  256 bits  ECDHE-ECDSA-AES256-SHA384
    Rejected  SSLv3  256 bits  ECDHE-RSA-AES256-SHA
...

  Prefered Server Cipher(s):
    TLSv1  128 bits  ECDHE-RSA-A...

Savon testing: How to expect any message

When using Savon to connect a SOAP API, you may want to use Savon::SpecHelper to mock requests in your tests as described in their documentation.

When sending a message body, the savon mock object requires a message to be set, like this:

savon.expects(:action_name).with(message: { user_id: 123 }).returns('<some xml>')

If you want to stub only the returned XML and do not care about request arguments, you can not omit with as Savon's helper will complain:

savo...

Jasmine: Testing AJAX calls that manipulate the DOM

Here is a Javascript function reloadUsers() that fetches a HTML snippet from the server using AJAX and replaces the current .users container in the DOM:

window.reloadUsers = ->
  $.get('/users').then (html) ->
    $('.users').html(html)

Testing this simple function poses a number of challenges:

  • It only works if there is a <div class="users">...</div> container in the current DOM. Obviously the Jasmine spec runner has no such container.
  • The code requests /users and we want to prevent network interaction in our uni...

Jasmine: Reset the location when testing code that uses pushState / replaceState

When testing code that uses pushState / replaceState, your browser will appear to navigate away from http://localhost:3000/specs (or wherever you run your Jasmine tests). This is inconvenient, since reloading the document will no longer re-run the test suite.

To remedy this, copy the attached file to a place like spec/javascripts/helpers and #= require it from your tests. It will store the current location before every test and reset if afterwards (using location.replaceState).

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...

Install or update Chromedriver on Linux

Option 0: Download from the official page (preferred)

Chromedriver must be available in your path. You can add ~/bin to your path like this:

echo "export PATH=$PATH:$HOME/bin" >> $HOME/.bash_profile

If you're also using Geordi, disable automatic updating of chromedriver in ~/.config/geordi/global.yml:

a...

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:

Perform Sidekiq jobs immediately in development

# config/initializers/sidekiq.rb

# Perform Sidekiq jobs immediately in development,
# so you don't have to run a separate process.
# You'll also benefit from code reloading.
if Rails.env.development?
  require 'sidekiq/testing'
  Sidekiq::Testing.inline!
end

Testing drag&drop with Selenium

When using jQueryUI's Sortable plugin (either directly or via Angular's ui.sortable), you might struggle testing your nice drag&drop GUI since Selenium webdriver does not support native dragging events.

But jQueryUI uses jquery.simulate for their testing, so why shouldn't you? There is even an extension to it that makes testing drag & drop quite easy.

Here is what you need:

  1. jquery.simulate.js
  2. [`jquery.simula...

How to test bundled applications using Aruba and Cucumber

Aruba is an extension to Cucumber that helps integration-testing command line tools.

When your tests involve a Rails test application, your tool's Bundler environment will shadow that of the test application. To fix this, just call unset_bundler_env_vars in a Cucumber Before block.

Previously suggested solution

Put the snippet below into your tool's features/support/env.rb -- now any command run through Aruba (e.g. via #run_simple) will have a clean Bundler envir...

Things to consider when using Travis CI

Travis CI is a free continuous integration testing service. However, it is really fragile and will break more than it will work.

If you choose to use it anyway, learn the lessons we already learnt:

Use a compatible Rubygems for Rails 2.3 on Ruby 1.8.7

Ruby 1.8.7 is not compatible with current Rubygems versions (> 2.0). Runnig rvm rubygems latest-1.8 --force will fix this and install Rubygems version 1.8.29.

To make Travis CI do this, add `before_script: rvm rubygems latest-1....

Collection of Rails development boosting frameworks

Development environment setup

Rails Composer
: Basically a comprehensive Rails Template. Prepares your development environment and lets you select web server, template engine, unit and integration testing frameworks and more.

Generate an app in minutes using an application template. With all the options you want!

Code generators

Rails Bricks
: A command line wizard. Once you get it running, it creates sleek applications.

RailsBricks enables you to creat...

Spreewald 0.7.0 brings better email steps, improved test suite

  1. You can now test for Reply-to

Then an e-mail should have been sent with:
"""
From: foo@bar.com
To: bar@baz.com
Reply-To: qux@bam.com
"""
  1. You can now specify the e-mail body after two line breaks

Then an e-mail should have been sent with:
"""
From: foo@bar.com
To: bar@baz.com

Message body goes here!
"""
  1. There are now more tests for e-mail steps
    ---------------------------------...

Custom RSpec matcher for allowed values (or assignable_values)

In contrast to RSpec's included allow_value matcher, the attached matcher will also work on associations, which makes it ideal for testing assignable_values.

Usage example

describe Unit do

  describe '#building' do
    it 'should only allow buildings that a user has access to' do
      building = build(:building)
      other_building = build(:building)
      unauthorized_building = build(:building)

      power = Power.new(build(:user))

      Power.with_power(power) do
        expect(power).to receive(:buildings).at_least...

Spreewald 0.6.1 makes it easier to inspect form values

The new version of Spreewald makes it easier to inspect form values.

Testing the value of any type of input control

  • When the step Then the "foo" field should contain "bar" is applied to a <select>, it now tests against option labels, not option values.
  • This is now consistent with Then "bar" should be selected for "foo".
  • This means you can now use Then the "foo" field should contain "bar" is applied to a <select> for all types of input ...