Using feature flags to stabilize flaky E2E tests
A flaky test is a test that is often green, but sometimes red. It may only fail on some PCs, or only when the entire test suite is run.
There are many causes for flaky tests. This card focuses on a specific class of feature with heavy side effects, mostly on on the UI. Features like the following can amplify your flakiness issues by unexpectedly changing elements, causing excessive requests or other timing issues:
- Lazy loading images
- Autocomplete in search f...
Setup Sidekiq and Redis
If you want Sidekiq to be able to talk to Redis on staging and production servers, you need to add the following to your configuration:
# config/initializers/sidekiq.rb
require 'sidekiq'
Sidekiq.configure_client do |config|
config.redis = { url: REDIS_URL }
end
Sidekiq.configure_server do |config|
config.redis = { url: REDIS_URL }
end
The following step may be skipped for new Sidekiq 6+, since it isn't recommended anymore to use a global redis client.
# config/initializers/redis.rb
require 'redis'
require_relativ...
RSpec: how to prevent the Rails debug page if you want to actually test for 404s
Within development and test environments, Rails is usually configured to show a detailed debug page instead of 404s. However, there might be some cases where you expect a 404 and want to test for it.
An example would be request-specs that check authorization rules. (If you use a gem like consul for managing authorization rules, you should always check these rules via power-specs. However, request-specs can be used as a light-weight version of integration tests here.)
In this case, Rails will replace the 404 page that you want to test ...
RSpec: automatic creation of VCR cassettes
This RailsCast demonstrated a very convenient method to activate VCR for a spec by simply tagging it with :vcr
.
For RSpec3 the code looks almost the same with a few minor changes. If you have the vcr
and webmock
gems installed, simply include:
# spec/support/vcr.rb
VCR.configure do |c|
c.cassette_library_dir = Rails.root.join("spec", "vcr")
c.hook_into :webmock
end
RSpec.configure do |c|
c.around(:each, :vcr) do |example|
name = example.metadata[:full_descripti...
RSpec: ". not_to include" behaves like ".to exclude"
RSpec is smart when using the include
-matcher in combination with .not_to
. One could assume that
.not_to include(3, 4, 5)
evaluates to:
NOT( .to include(3, 4, 5) )
However, it behaves like:
.to (NOT include(3) && NOT include(4) && NOT include(5) )
Warning
Using
.not_to
in combination with theinclude
-matcher doesn't logically negate the final truth value. It instead negates the individual include-expectations for each argument.
Proof
describe 'RSpec' do
it "doesn't use logical nega...
A Guide To CSS Debugging
Debugging in CSS means figuring out what might be the problem when you have unexpected layout results. We’ll look at a few categories bugs often fit into, see how we can evaluate the situation, and explore techniques that help prevent these bugs.
Fix REPL of better_errors page
The gem better_errors offers a detailed error page with an interactive REPL for better debugging.
I had the issue that on a few projects with Ruby 2.5.8
, the REPL was not shown.
Solution
To make the REPL work properly with this Ruby version I had to update the gem binding_of_caller to at least version 0.8.0
.
From the [better_errors](https://github.com/BetterE...
Git shortcut to rebase onto another branch
Inspired by recent "git shortcut" cards I figured it would be nice to have one of these for rebasing a few commits onto another branch. The usual notation is prone to of-by-one errors as you have to either specify the commit before the ones you want to move or count the number of commits.
You may add this rebase-onto
function to your ~/.bashrc
:
function rebase-onto {
commit=$(git log --oneline | fzf --prompt 'Select the first commit y...
Cancelling the ActiveRecord callback chain
What | Rails version | Within before_*
|
Within after_*
|
---|---|---|---|
Cancel later callbacks | Rails 1-4 | return false |
return false |
Cancel later callbacks | Rails 5+ | throw :abort |
throw :abort |
Rollback the transaction | Rails 1-4 | return false |
raise ActiveRecord::Rollback |
Rollback the transaction | Rails 5+ | `thr... |
Capybara can find links and fields by their [aria-label]
Sometimes a link or input field has no visible label. E.g. a text field with a magnifying glass icon 🔎 and a "Search" button does not really need a visible label "Query".
For accessibility reasons it is good practice to give such a field an [aria-label]
attribute:
<input type="search" aria-label="Search contacts">
This way, when a visually impaired user focuses the field, the screen reader will speak the label text ("Search contacts").
Info
Without an `[aria-...
Disable built-in dragging of text and images
Most browsers have built-in drag and drop support for different page elements like text and images. While this may be useful in most situations, it may become annoying in others. If you e.g. want to allow the user to scroll/move horizontally within a container by grabbing an item and moving the mouse, you will notice that nothing will move and you'll instead start dragging that element.
To disable this, add the following CSS to your content:
-webkit-user-drag: none
user-drag: none
-webkit-user-drag
is only fully supported in ...
Webpack(er): A primer
webpack is a very powerful asset bundler written in node.js to bundle (ES6) JavaScript modules, stylesheets, images, and other assets for consumption in browsers.
Webpacker is a wrapper around webpack that handles integration with Rails.
This is a short introduction.
Installation
If you haven't already, you need to install node.js and Yarn.
Then, put
gem 'webpacker', '~> 4.x' # check if 4.x is still cu...
Bash alias to switch between recent branches
If you have fzf installed, you may add an alias such as this to your ~/.bashrc
:
alias recent-branch="git for-each-ref --sort=-committerdate --format='%(refname:short)' refs/heads/ | fzf | sed 's/\* //g' | xargs -I '{}' git checkout {}"
alias rb=recent-branch
Now whenever you want to switch back and forth between your most recent branches, type recent-branch
, select one and press enter.
Large CSS box shadows can bring browsers to a crawl
Browser rendering engines are very slow at rendering large box shadows. I had a situation where a complex layout with fixed elements and large shadows slowed Firefox down to 2 frames/second for scrolling and DOM manipulation.
Some advice:
- Be aware that by introducing fixed elements (e.g. sticky navigation bars) and large animations, you might force the browser to redraw large portions of the site when scrolling. When your fixed elements have shadows, this increases the screen area that needs to be redrawn, which might again require other...
Rails: Removing the cucumber-rails warning when setting cache_classes to false without Spring enabled
We are using Spring in our tests for sequential test execution but not for parallel test execution. And Rails requires you to set the config.cache_classes = false
if you are using Spring in tests.
With our setup, this would raise the following error in cucumber-rails for parallel test executions due to some legacy database cleaner issue.
WARNING: You have set Rails' config.cache_classes to false
(Spring needs cache_classes set to false). This is known to cause probl...
Working on the Linux command line: How to use bookmarks for directories
Bookmarks for directories will be most helpful if you are forced to work in deeply nested projects. Then it's really helpful!
This makes use of the CDPATH
variable. Similar to the PATH
variable, which holds the list of directories which are searched for executables, CDPATH
contains the list of directories that are available for cd
. Besides the current directory (.
), you can add others to that.
The trick is to add a directory for bookmarks to CDPATH
.
First, create the directory with: mkdir ~/.bookmarks
.
Then add the followin...
Working on the Linux command line: How to efficiently navigate up
With cd ..
you can navigate one directory up from the one you are at now. If you use that a lot, consider some handy aliases.
Add the following lines to your ~/.bashrc
:
alias ..="cd .."
alias ...="cd ../.."
alias ....="cd ../../.."
alias .....="cd ../../../.."
alias ......="cd ../../../../.."
you can add even more aliases, but I usually loose track after too many levels and just jump to the directly directly, e.g. using its absolute path or its bookmark (see [this card](https://makandracards.com/makandra/504947-working-on-the-li...
The many gotchas of Ruby class variables
TLDR: Ruby class variables (@@foo
) are dangerous in many ways. You should avoid them at all cost. See bottom of this card for alternatives.
Class variables are shared between a class hierarchy
When you declare a class variable, it is shared between this and all descending (inheriting) classes. This is rarely what you want.
Class variables are bound at compile-time
Like unqualified constants, class variables are bound to your current scope *whe...
Encrypting messages with age (alternative to PGP)
age is a simple, modern and secure file encryption tool, format, and Go library.
It features small explicit keys, no config options, and UNIX-style composability.
Generally we are happy with GPG for encrypting emails. In case you are not happy with the CLI of GnuPG
, this might be a tool you can use under the hood for encryption.
Unpoly 2: Don't try to download files through AJAX requests
Rails has the handy controller method send_file which lets us download files easily. We can decide whether the file should be downloaded (disposition: 'attachment'
) or shown in the browser (disposition: 'inline'
). The default is disposition: 'attachment'
.
Downloading files will not work when you are calling the controller action from an AJAX request. The browser will try to render the file and insert it in the DOM, which is never what you want.
Unpoly 2
Unpoly (sin...
Webpack: How to avoid multiple versions of jQuery
To avoid multiple versions of a package, you can manually maintain a resolutions
section in your package.json
. We recommend you to do this for packages like jQuery. Otherwise the jQuery library attached to window
might not include the functions of your packages that depend on jQuery.
Note: This is only an issue in case you want to use a package functionality from window
e.g. $(...).datepicker()
from your dev console or any other javascript within the application.
Background
By default yarn will create a folder node_modules
...
Cucumber Factory: How to assign polymorphic associations
Cucumber factory supports polymorphic associations out of the box. Just keep in mind that you need to use named associations for this purpose.
class Person < ApplicationModel
has_many :buildings, inverse_of: :owner
end
class Company < ApplicationModel
has_many :buildings, inverse_of: :owner
end
class Building < ApplicationModel
belongs_to :owner, optional: true, polymorphic: true
end
Works
Given there is a person with the name "Nice person"
And there is a bui...
Bookmarklet to facilitate generating new git branches for PivotalTracker Stories
This bookmarklet grabs a PivotalTracker story title, transforms it into a valid git branch name and automatically prepends your initials and an optional abbreviation (for better tab completion). It will output the following formats:
If you cancel the first dialog or confirm it without entering text:
git checkout -b kw/178298638-card-320-state-machines
If you enter an abbreviation (e.g. stm
in this case):
git checkout -b kw/stm/178298638-card-320-state-machines
How to set it up:
- in the attached file replace `YOUR_INITI...
Unobtrusive JavaScript helper to progressively enhance HTML
The attached compiler()
function below applies JavaScript behavior to matching HTML elements as they enter the DOM.
This works like an Unpoly compiler for apps that don't use Unpoly, Custom Elements or any other mechanism that pairs JavaScript with HTML elements.
The compiler()
function is also a lightweight replacement for our legacy [$.unobtrusive()
](https://makandracards.com/makandra/4-unobtrusiv...