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:
- Methods from the object's singleton class (an unnamed class that only exists for that object)
- Methods from prepended modules (Ruby 2.0+ feature)
- Methods from the object's class
- Methods from included modules
- 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:
- 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...