BrowserStack has browser plugins for local testing

Local testing allows you to test your private and internal servers using the BrowserStack cloud, which has support for firewalls, proxies and Active Directory.

How to simulate limited bandwidth in Google Chrome and Firefox

Your development machine is usually on a very good network connection.
To test how your application behaves on a slow network (e.g. mobile), you can simulate limited bandwidth.

Chrome

  • Open the dev tools (Ctrl+Shift+I or F12) and switch to the "Network" tab
  • In the row below the dev tool tabs, there's a throttling dropdown which reads "Online" by default.
  • Inside the dropdown, you will find a few presets and an option to add your own download/upload/latency settings.

Firefox

  • Open the dev tools (Ctrl+Shift+I or F12) and switc...

JavaScript: How to log execution times to your browser console

If you are trying to inspect timings in JavaScript, you can use console.time and console.timeEnd which will write to your browser console.

Example:

console.time('lengthy calculation');
lengthyCalculation();
console.timeEnd('lengthy calculation');

lengthy calculation: 1.337ms

Note that this allows using console.timeEnd in another context which is helpful when you are doing things asynchronously, or just in different places.

Works in all browsers, including recent Internet Explorers. For older IEs, you may activate...

How Ruby method lookup works

When you call a method on an object, Ruby looks for the implementation of that method. It looks in the following places and uses the first implementation it finds:

  1. Methods from the object's singleton class (an unnamed class that only exists for that object)
  2. Methods from prepended modules (Ruby 2.0+ feature)
  3. Methods from the object's class
  4. Methods from included modules
  5. Methods from the class hierarchy (superclass and its an...

Why belongs_to/has_many cannot overwrite methods with the same name

When you use a belongs_to or has_many macro you might be surprised that the methods that it generates does not override a method with the same name. Take this example:

class Project < ActiveRecord::Base
  
  def user
    "foo"
  end
  
  belongs_to :user
  
end

Project.new.user still returns "foo".

The reason for this is that what belongs_to does is actually this:

class Project < ActiveRecord::Base
  include FeatureMethods
  
  def user
    "foo"
  end
  
end

module Project::FeatureMethods

  def user
    # ass...

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

Cucumber does not find neither env.rb nor step definitions when running features in nested directories

Usually, Cucumber feature files live in features/. When you group them in sub directories, make sure to add -r features to the standard Cucumber options.

In Rails apps, Cucumber options are likely to be stored in config/cucumber.yml.

Don't build randomness into your factories

Tests are about 100% control over UI interaction and your test scenario. Randomness makes writing tests hard. You will also push tests that are green for you today, but red for a colleague tomorrow.

That said, please don't do something like this:

Factory(:document) do |document|
  document.category { ['foo', 'bar', 'baz'].sample }
end

Instead do this:

Factory(:document) do |document|
  document.category 'foo'
end

The case against Faker

I even recommend to not use libraries like [Faker]...

Cucumber: Wait until CKEditor is loaded

I had to deal with JavaScript Undefined Error while accessing a specific CKEditor instance to fill in text.

Ensure everything is loaded with

patiently do
  page.execute_script("return isCkeditorLoaded('#{selector}');").should be_true
end

Example

The fill in text snippet for Cucumber:

When /^I fill in the "([^\"]+)" WYSIWYG editor with:$/ do |selector, html|
  patiently do
    page.execute_script("return isCkeditorLoaded('#{selector}');").should be_true
  end
  html.gsub!(/\n+/, "") # otherwise: unterminated string lit...

Namespacing: why `uninitialized constant` error may occour in `development` but not in `test` environment

Example:

  class Book::Page
  end
  
  class MyBook < Book
    def new_page
      Page.new # has to be `Book::Page` in development to make it work 
    end
  end

Method new_page may throw an error when it was called during browser interaction in development but doesn't make the test fail.

The reason

Development autoloading isn't smart enough to find the referenced class
At other environments (test, staging, production) autoloading is disabled, that all classes are already loaded when browser interaction takes place what makes...

Howto prompt before accidentally discarding unsaved changes with JavaScript

Ask before leaving an unsaved CKEditor

Vanilla JavaScript way, but removes any other onbeforeunload handlers:

  $(function(){
    document.body.onbeforeunload = function() {
      for(editorName in CKEDITOR.instances) {
        if (CKEDITOR.instances[editorName].checkDirty()) {
          return "Unsaved changes present!"
        }
      }
    }
  }

A robuster implementation example

Note: Don't forget to mark the 'search as you type' forms with the skip_pending_changes_warning class.

var WarnBeforeAccidentallyDiscard...

How to call overwritten methods of parent classes in Backbone.js

When you are working with Backbone models and inheritance, at some point you want to overwrite inherited methods but call the parent's implementation, too.
In JavaScript, there is no simple "super" method like in Ruby -- so here is how to do it with Backbone.

Example

BaseClass = Backbone.Model.extend({
  initialize: function(options) {
    console.log(options.baseInfo);
  }
});

MyClass = BaseClass.extend({
  initialize: function(options) {
    console.log(options.myInfo);
  }
});

ne...

Custom error messages in RSpec or Cucumber steps

Sometimes you have a test expectation but actually want a better error message in case of a failure. Here is how to do that.

Background

Consider this test:

expect(User.last).to be_present

In case of an error, it will fail with a not-so-helpful error message:

expected present? to return true, got false (Spec::Expectations::ExpectationNotMetError)

Solution

That can be fixed easily. RSpec expectations allow you to pass an error message like this:

expect(User.last).to be_present, 'Could not find a user!'

...

How to doubleclick in Selenium

Put the attached file into features/support/.

Example usage:

When /^I open the task named "(.+?)"$/ do |task_name|
  task = page.all('.task').detect do |t|
    t.find('.label').text.downcase == task_name.downcase
  end
  
  task.double_click
end

Note: only Selenium understands doubleclicks.\
Credits: the attached Capybara issue discussion.

Protip: Always leave a failing test

Mornings can be rough. To make them a little easier, leave yourself a failing test if your work isn’t finished. When you come back to the project, it makes it much easier to understand where you were and figure out what you still need to do.

Resolving Element cannot be scrolled into view (Selenium::WebDriver::Error::MoveTargetOutOfBoundsError) on Mavericks

After I upgraded to Mac OS X Mavericks, I regularly got this error message when running Cucumber features with Selenium:

Element cannot be scrolled into view:[object XrayWrapper [object HTMLInputElement]] (Selenium::WebDriver::Error::MoveTargetOutOfBoundsError)

I had the Terminal window running the test on my secondary screen, whereas the Selenium-webdriven Firefox always started on my primary one. Now if I had focused the secondary screen when running the tests, Selenium could not start Firefox and switch to it (probably because t...

Ruby number formatting: only show decimals if there are any

Warning: Because of (unclear) rounding issues and missing decimal places (see examples below),
do NOT use this when dealing with money. Use our amount helper instead.


In Ruby, you can easily format strings using % (short for Kernel#sprintf):

'%.2f' % 1.23456 #=> 1.23
'%.2f' % 2 #=> 2.00

However, what if you only want the decimals to be shown if they matter? There is g! It will limit the total number of displayed digits, disregarding...

CSS: Opacity is not inherited in Internet Explorer

Non-static elements will not inherit their parent's opacity in IE for no good reason. This can lead to unexpected behaviour when you want to fade/hide an element and all its children.

To fix it, give the parent element defining the opacity a non-static positioning. For example:

.parent {
  opacity: 0.2;
  position: relative; /* for IE */
}

While the linked article describes this problem for IE9 and below, I have encountered the same issue in IE10 and IE11.

Just go away, Internet Explorer!

MySQL 5.6 slightly changes DECIMAL data type

About

A MySQL DECIMAL column is used when it is important to preserve exact precision. It takes two parameters, where precision is the total number of digits and scale the number of digits to the right of the decimal point. A DECIMAL(6,2) column may store numbers up to 9,999.99.

In Rails, a decimal column definition looks like this: t.decimal :amount, :precision => 6, :scale => 2.

Issue

MySQL prior to 5.6 stored leading zeros (0003.1) and +/- characters (+2.1) within the column. However, **it would permit storing ...

The new Modularity 2 syntax

We have released Modularity 2. It has many incompatible changes. See below for a script to migrate your applications automatically.

There is no does method anymore

We now use traits with the vanilla include method:

class Article < ActiveRecord::Base
  include DoesTrashable
end

When your trait has parameters, use square brackets:

class Article < ActiveRecord::Base
  include DoesStripFields[:name, :brand]
end

Note how you ...

Cucumber / Selenium: Access and test document title

If you want to test that a certain text is contained within the document title of your page, you can do so using Selenium and a step such as

Then /^"(.*?)" should be shown in the document title$/ do |expectation|
  title = page.driver.browser.title
  title.should include(expectation)
end

Careful with '||=' - it's not 'memoize'

When you do something like this in your code:

def var_value
  @var ||= some_expensive_calculation
end

Be aware that it will run some_expensive_calculation every time you call var_value if some_expensive_calculation returns nil.

This illustrates the problem:

def some_expensive_calculation
  puts "i am off shopping bits!"
  @some_expensive_calculations_result
end

When you set @some_expensive_calculations_result to nil, ||= runs some_expensive_calculation every time....

Threads and processes in a Capybara/Selenium session

TLDR: This card explains which threads and processes interact with each other when you run a Selenium test with Capybara. This will help you understand "impossible" behavior of your tests.


When you run a Rack::Test (non-Javascript) test with Capybara, there is a single process in play. It runs both your test script and the server responding to the user interactions scripted by your test.

A Selenium (Javascript) test has a lot more moving parts:

  1. One process runs your test script. This is the process you...

Ruby constant lookup: The good, the bad and the ugly

In Ruby, classes and modules are called constants. This card explains how Ruby resolves the meaning of a constant.

The good

E. g. in the following example, Array could mean either Foo::Array or simply Array:

class Foo
  def list
    Array.new
  end
end

What Ruby does here is to see if the name Array makes sense inside of Foo::, and if that fails, resolves it to ::Array (without a namespace).

The bad

This is relevant for old Ruby versions. Ruby 2.5+ removes top-level constant lookup whi...