How to set up database_cleaner for Rails with Cucumber and RSpec
Add gem 'database_cleaner'
to your Gemfile. Then:
Cucumber & Rails 3+
# features/support/database_cleaner.rb
DatabaseCleaner.clean_with(:deletion) # clean once, now
DatabaseCleaner.strategy = :transaction
Cucumber::Rails::Database.javascript_strategy = :deletion
Cucumber & Rails 2
The latest available cucumber-rails
for Rails 2 automatically uses database_cleaner
when cucumber/rails/active_record
is required -- but only if transactional fixtures are off. To have database_cleaner
work correctly:
- Add the at...
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)...
How to view a file from another branch
Just run git show branch:file
. Examples:
git show HEAD~:bin/command
git show origin/master:../lib/version.rb
ImageMagick: Cropping images
ImageMagick takes a string with several options when cropping an image. See the command line options for how to provide the expected image geometry for details.
Note that ImageMagick tends to preserve the original aspect ratio of the source image automatically.
Examples:
-
crop 200x200
means Maximum values of height and width given, aspect ratio preserved. -
crop 200x200!
means Width and height emphatically given, original aspect ratio ignored.
Jasmine 2 cheat sheet for RSpec lamers
In the tradition of our PostgreSQL cheat sheet for MySQL lamers, here is a cheat sheet for Jasmine when you're used to RSpec.
Note that Jasmine syntax has changed with Jasmine 2, so if you're using Jasmine 1.x you might instead want to use an older cheat sheet.
Expectations
# RSpec
expect(foo).to.eq("value")
expect(foo).to_not eq("value")
# Jasmine
expect(foo).toBe("value")
expect(...
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
).
How to upgrade Cucumber on Rails 3+
-
Run
bundle update cucumber capybara cucumber-rails
to update to the newest versions. -
Backup your
features/support/path.rb
to be able to add your own paths again after the cucumber installation script in step 4. -
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'
-
Run `$ rails generate cucumber:install --capyba...
AngularJS: Binding to Perl-style getter/setters functions
Angular 1.3+ has an alternative getter/setter pattern: You can bind ng-model
to an accessor function. This is a function that is either a getter (when it gets no arguments) or a setter (when it gets the new value as an argument):
$scope.name = function(newName) {
return angular.isDefined(newName) ? (_name = newName) : _name;
}
You need to bind this function with ng-model
and `ng-model-options="{ getterSette...
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 [...
Action Mailer Previews
Rails includes a way to see what an e-mail will look like.
Integration to RSpec
All you need to do is implement a preview-class in spec/mailers/previews/notifier_preview.rb
:
class NotifierPreview < ActionMailer::Preview
def welcome
Notifier.welcome(User.first)
end
end
And adapt the preview load path in your application.rb
:
config.action_mailer.preview_path = "#{Rails.root}/spec/mailers/previews" # For Rails < 7.1
config.action_mailer.preview_paths << "#{Rails.root}/spec/mailers/previews" # For Rails >=...
The developer console can do more than you think!
You can do so much more than console.log(...)
! See the attached link for a great breakdown of what the developer console can give you.
Some of my favorites:
console.log takes many arguments
E.g. console.log("Current string:", string, "Current number:", 12)
Your output can have hyperlinks to Javascript objects
E.g. console.log("Check out the current %o, it's great", location)
[Di...
Active Record and PostgreSQL — Ruby on Rails Guides
Rails guide that covers PostgreSQL-specific column types and usages for Active Record.
You should especially keep in mind the special datatypes that PostgreSQL offers. \
Types like json
and array
take away a lot of the pain that you had on MySQL projects.
Example use cases for array
are tags or storing foreign keys (instead of a join model). You can even index them.
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/
.
RSpec matcher "be_sorted"
RSpec::Matchers.define :be_naturally_sorted do
match do |array|
array == array.natural_sort
end
end
See RSpec: Where to put custom matchers and other support code. To use natural_sort
, see this card.
This matcher is now part of Spreewald.
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...
Fixing the warning Time#succ is obsolete; use time + 1
Chances are you're seeing the warning repeated a lot of times, maybe thousands of times. Here's how to reproduce the issue:
Example 1
# bad code
(Time.current .. Time.current + 1.hour).include?(Time.current)
# Use Range#cover? instead of Range#include? since the former does no typecasting into integers.
(Time.current .. Time.current + 1.hour).cover?(Time.current)
Example 2
# bad code
Post.where(:created_at => min_date.beginning_of_day .. max_date.end_of_day)
# Use 'BETWEEN x AND y'
Post.where(['posts.created_at BETWEEN...
How to emulate simple classes with plain JavaScript
If you want a class-like construct in JavaScript, you can use the module pattern below. The module pattern gives you basic class concepts like a constructor, private state, public methods.
Since the module pattern only uses basic JavaScript, your code will run in any browser. You don't need CoffeeScript or an ES6 transpiler like Babel.
A cosmetic benefit is that the module pattern works without the use of this
or prototypes.
Example
Here is an example for a Ruby class that we want to translate into Javascript using the module patter...
AngularJS: How to remove a watch
Sometimes you want Angular to watch an object only until a certain state is reached (e.g. an object appears in the scope).
Angular's $watch
returns a method that you can call to remove that watch. For example:
unwatch = $scope.$watch 'user', (user) ->
if user?
... # do something
unwatch()
That's it.
Heads up: LibreOffice Calc adds quotation marks when copying data from multi-line cells
Copy data from LibreOffice Calc
When you copy data from multi-line cells in LibreOffice Calc, quotation marks are automatically added, which you may not want.
For example with license keys:
09:46:24 [✔] pascal:~> icdiff license license_copy
license license_copy
===== LICENSE BEGIN ===== "===== LICENSE BEGIN =====
00000yIeXfhGSbt"yULWQR9n 00000yIeXfhGSbt""yULWQR9n
olysFAv105bHmKOiqbxRX"Yr ...
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...