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

Change commit messages of past Git commits

To change a commit message of the most recent (unpushed) commit, you can simply use
git commit --amend -m 'new message'

To change messages of (unpushed) commits further in the past:

git rebase -i [COMMIT BEFORE THE FIRST YOU WANT TO EDIT]

Mark all messages to be changed with "edit".

Git will start the rebasing and stop at every marked commit. For each of those, do a
git commit --amend -m 'new message'
git rebase --continue

Test a gem in multiple versions of Rails

Plugins (and gems) are typically tested using a complete sample rails application that lives in the spec folder of the plugin. If your gem is supposed to work with multiple versions of Rails, you might want to use to separate apps - one for each rails version.

For best practice examples that give you full coverage with minimal repitition of code, check out our gems has_defaults and assignable_values. In particular, take a look at:

  • Multiple `sp...

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

Useful collection of Sass mixins

This collection of Sass mixins enables cross-browser styling (including IE with CSS3PIE) with less lines of code.

This enables PIE for IE up to version 8 only (the first part is not possible in Haml, so use ERB):

<!--[if !IE]><!-->
  <%= stylesheet_link_tag 'screen', :media => 'screen' %>
<!--<![endif]-->
<!--[if lte IE 8]>
  <%= stylesheet_link_tag 'screen_with_pie', :media => 'screen' %>
<![endif]-->

These would be your two screen Sasses:

# screen_with_pie.sass

...

Enable SSL for Pivotal Tracker

You should never transmit sensitive data without encryption. Being logged in somewhere constitutes transmitting sensitive data.

For Pivotal Tracker:

  • Make sure you set "Always Use HTTPS" under "My Profile".
  • As you can not rely on every member of a project to have this enabled, you should also tick "Use HTTPS" on the settings page of each project.

Trigger an event with Javascript

This is non-trivial because you need to fake event objects and require different code for different browsers. Luckily, there is tool support for most types of events.

In jQuery you can say:

$('a#close_window').click();

In Prototype you can use event.simulate.js from the Protolicious library to say:

$$('a#close_window')[0].simulate('click');

To trigger custom events with Prototype, you can use the [built-in Element.fire()](http://api.prototypejs.org/dom/...

kangax's protolicious - GitHub

Added utility methods for the Prototype Javascript framework.

Cross-browser height and line-height

When using an odd value for line-height in CSS the result will vary across all major browsers.\
Use an even line-height whenever possible.


When you are styling block elements you often apply both height and line-height to them. This Sass mixin helps you out with odd heights by always setting an even line height:

=height($height)
  height: $height
  line-height: floor($height / 2) * 2

So when you call +height(19px) in Sass this will be the resulting CSS:

height: 19px
line-...

Retrieve the total number of records when paginating with will_paginate

When you use will_paginage to paginate a scope, and you want to obtain the total number of records matched before pagination, you can use total_entries:

users = User.active.paginate
puts users.count # number of records on this page, e.g. 50
puts users.total_entries # total number of records before pagination, e.g. one billion trillion

This will trigger a second database query in order to retrieve the count (which will run anyway if you render any kind of pagination widget).


`wil...

Keep Pidgin up to date

If your pidgin IM fails to connect to ICQ, you may need to update it. The ubuntu default sources are usually outdated.

Just follow the instructions 1-4 and 1-3 on the page linked below.

Making SSL connection work

If you can not connect using SSL, open up the account settings and enable "clientLogin". Also, your Server should be set to slogin.icq.com.

Making AJAX Applications Crawlable

This document describes an agreement between web servers and search engine crawlers that allows for dynamically created content to be visible to crawlers. Google currently supports this agreement. The hope is that other search engines will also adopt this proposal.

Problems with Rails 3 Remote Links and Forms Using jQuery .live() in IE

There is a problem with AJAX response handling for Rails 3 remote links and forms in Internet Explorer. This problem affects applications still using jQuery 1.4.2.

Git: Stash unstaged changes

This will stash all modifications that you did not git add:

git stash -k

Note that newly created (and non-added) files will remain in your working directory unless you also use the -u switch.

git stash -k -u

Also, your working directory must be clean (i.e. all changes need to be added) when you git stash pop later on.

Bookmarklet to generate a commit message with Pivotal Tracker story ID and title

For clarity and traceability, your commit messages should include the ID and title of the Pivotal Tracker story you're working on. For example:

[#12345] Add Google Maps to user profiles
Optional further commit messages in the body

Also see Howto: Write a proper git commit message

To quickly generate such commit messages, add a new link "Commit" to your bookmarks and use the following Javascript as the link URL:

javascript:(function() { ...

scribd's flash_heed at master - GitHub

Fixes all Flash elements on a page so that they heed DOM stacking order

Change the id of an ActiveRecord record

You most likely never want to do this. But if you do:

Model.update_all({:id => new_id}, {:id => old_id})

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

Aliases for routes

The following initializer provides an :alias => "my_route_name" option to restful routes in your route.rb. This simply makes the same route also available under a different ..._path / ..._url helpers.

For example,

map.resources :notes, :alias => :snippets

Gives you

notes_path, notes_url, new_note_path... #as always
snippets_path, snippets_url, new_snippet_path... #from the alias

Put this into an initializer:

Git: "Interactive reverts"

If you need to revert only parts of one or several commits the following workflow can help:

If you need to revert multiple changes, make a branch and squash it afterwards.

For every commit you need to revert, starting at the most recent, do:

git revert -n [COMMIT] #revert, but don't automatically commit
... #fix any conflicts
git reset #unstage all changes
git add -p #this will ask you for every change, whethe...

Git diff a file with another revision (or branch)

git diff commit_hash -- path/to/file

Provide any commit hashes or branch names like "master" for commit_hash.

Install a specific version of a gem

To install webmock 1.5.0:

sudo gem install webmock --version "=1.5.0"

or
sudo gem install webmock -v "=1.5.0"

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

Generate a Unicode nonbreaking space in Ruby

Regular spaces and non-breaking spaces are hard to distinguish for a human.
Instead of using the &nbsp; HTML entity or code like " " # this is an nbsp, use a well-named helper method instead.

def nbsp
  [160].pack('U*')
end

160 is the ASCII character code of a non-breaking space.