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

Working on the Linux command line: How to bash `cd` with autocorrect

There is an option you can set so that when using the cd command, small typos are automatically corrected. Add the following to your ~/.bashrc:

# cd: autocorrect small typos and use best guess
shopt -s cdspell 

Example:

cd Porjects
# Projects

pwd
# /home/judith/Projects

Also, I recommend adding aliases for your most common typos of commands you regularly use to your ~/bashrc. Which ones that are is highly personal, for me it's e.g. tig:

alias tog='tig'
alias tug='tig'

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

Using attribute event handlers with a strict Content Security Policy (CSP)

Given you have a strict CSP that only allows <script src> elements from your own domain:

Content-Security-Policy: script-src 'self'

This will block JavaScript handlers inlined as attribute into your HTML elements. Clicking on the following link will only log an error with a strict CSP:

<a href="javascript:alert('hello')">click me</a>
<a href="#" onclick="alert('hello')">click me</a>

Solution 1: Move the handler into your JavaScript

The recommended solution is to move the handler from the HTML to the allowed ...

Spreewald development steps

Our gem spreewald supports a few helpers for development. In case you notice errors in your Cucumber tests, you might want to use one of them to better understand the underlying background of the failure. The following content is also part of the spreewald's README, but is duplicated to this card to allow repeating.

Then console

Pauses test execution and opens an IRB shell with current cont...

Setting SASS variables as value for CSS custom properties

When using custom properties in your stylesheets, you may want to set a specific property value to an existing variable in your SASS environment. A pratical example would be a list of color variables that you've defined in colors.sass and that you would like to refer to in your stylesheets. However, simply assigning a variable will not work:

$my-great-blue: blue

:root
  --my-color: $my-great-blue

.sky
  background-color: var(--my-color)

The property value will not be valid and if you open the browser's inspection window, yo...

Headless Chrome: Changing the Accept-Language header is not possible

It seems like changing the HTTP_ACCEPT_LANGUAGE is not possible for a headless chrome.

  • On Ubuntu the headless Chrome derives the Accept-Language from the operation system
  • Adding the option options.add_argument('--lang=de') to the Capybara::Selenium::Driver has no effect
  • Adding the preference options.add_preference('intl.accept_languages', 'de') to the Capybara::Selenium::Driver has only effects if the --headless option is skipped (see bug ticket #775911)
  • Cha...

Selenium: Network throttling via Chromedriver

You can throttle the network in your headless chrome via Selenium. This might be useful for debugging issues with flaky integration tests or slow page simulations.

page.driver.browser.network_conditions = {offline: false, latency: 5, download_throughput: 2 * 1024, upload_throughput: 2 * 1024}

The settings will match to the following UI component in Chrome:

Image

Were the values for the default profiles might match the values from this post:

**S...

Modern HTTP Status codes for redirecting

Formerly 301 (Moved Permanently) and 302 (Found) were used for redirecting. Browsers did implement them in different ways, so since HTTP 1.1 there are some new status codes which allow for finer distinctions.

The interesting part is how non-GET requests are handled by the redirect. It is preferrable to use the newer status code to avoid unexpected behavior.

303 See Other

The response to the request can be found under anot...

GitHub Actions: Manually running a workflow

To start a workflow manually it must have a trigger called workflow_dispatch:

---
name: Tests
on:
  push:
    branches:
    - master
  pull_request:
    branches:
    - master
  workflow_dispatch:
    branches:
    - master  

In the Actions tab of your repo you can now select a workflow and press "Run Workflow".

See GitHub documentation for details.

GitHub Actions: Retrying a failing step

If you have a flaky command you can use the nick-invision/retry to re-try a failing command, optionally with a timeout:

---
...
jobs:
  test:
    ...
    steps:
    - name: Run tests
      uses: nick-invision/retry@v2
      with:
        timeout_seconds: 30
        max_attempts: 3
        command: bundle exec rake spec

How to checkout submodules in Gitlab CI

Accessing other repositories in Gitlab CI is not straight forward, since the access rights of the current pipeline might not be sufficient enough.

One approach is to use project access tokens and clone the repositories via HTTPS.

  • Create a project access token for all submodules you want to have access to with the setting read_repository
  • Add the secrets as environment variable to the main project you want to have access to submodules:
    • Protected false ...

Undefined method log for Selenium::WebDriver::Remote::W3C::Bridge

In case your integration tests crash with a message like below, try to upgrade Capybara to a newer version (3.35.3 was good enough). You might encounter this issue when you enabled the w3c option in Selenium.

undefined method `log' for #<Selenium::WebDriver::Remote::W3C::Bridge:0x000055995647ded0>

Your affected code might look similar to this call below and will work after the upgrade again.

Upgrading Capybara with deprecated Integer selectors

Capybara added a deprecation warning in version 3.35.3 (version from 2019) that shows up if your selector is not of type String or Symbol.

Example:

click_link(10) # bad
click_link("10") # good

You might encounter this error e.g. in a pagination step or similar where you want to click on numbers. To figure out where this deprecation warning comes from try to run the tests with a step output.

bundle exec parallel_cucumber --test-options "--format=pretty" feature

The deprecation message looks like following:

Locator In...

Geordi 6.0.0 released

6.0.0 2021-06-02

Compatible changes

  • geordi commit will continue even if one of the given projects is inaccessible. It will only fail if no stories could be found at all.

Breaking changes

Chromedriver: Disabling the w3c option might break your integration tests with Chrome 91

We recently noticed issues with Chrome 75+ when having the w3c option enabled within the Selenium webdriver. It looks like recent Selenium versions don't have any issues with the w3c interface anymore. And starting with Chrome 91 this fix might cause unexpected issues, so you should try to enabled this option again or just remove the following line from you configuration:

options.add_option('w3c', false)

Background: Setting the w3c option t...

Accessing JavaScript objects from Capybara/Selenium

When testing JavaScript functionality in Selenium (E2E), you may need to access a class or function inside of a evaluate_script block in one of your steps. Capybara may only access definitions that are attached to the browser (over the window object that acts as the base). That means that once you are exporting your definition(s) in Webpacker, these won't be available in your tests (and neither in the dev console). The following principles/concepts also apply to Sprockets.

Say we have a StreetMap class:

// street_map.js
class S...

Heads up: Byebug has problems with zeitwerk

I encountered a unlucky behavior of byebug 11.1.3 (the most recent version at time of writing) when using it with Rails 6 and it's new autoloading component, zeitwerk. There already is a issue for that, so I hope it will be fixed with a future release.

The following test succeeds:

  context 'factories' do
    let(:test_case) { FactoryBot.create(:test_case) }
    it 'are valid' do
      expect(test_case).to be_valid
    end
  end

But when I did the same in byebug the foll...

RSpec: Ensuring a method is called on an object that will be created in the future

rspec >= 3.1 brings a method and_wrap_original. It seems a bit complicated at first, but there are use cases where it helps to write precise tests. For example it allows to add expectations on objects that will only be created when your code is called.

If you have older rspec, you could use expect_any_instance_of, but with the drawback, that you can't be sure if it really was the correct instance which got the message.

Example

The example model uses different validators based on a flag:

class MyModel < ApplicationRecord

 ...

Ruby: Fixing strings with invalid encoding and converting to UTF-8

When dealing with external data sources, you may have to deal with improperly encoded strings.
While you should prefer deciding on a single encoding with the data-providing party, you can not always force that on external sources.
It gets worse when you receive data with encoding declaration that does not reliably fit the accompanying string bytes.

Here is a Ruby class that helps converting such strings to a proper encoding.
Note that it tries several approaches of changing the encoding. **This is not a silver bullet and may or may not work...

Disabling client caching with Cache-Control: no-store

Browsers usually cache website content in order to provide the user with faster responses. Examples are returning to a website using the "Back" button, or reopening a browser and restoring previous tabs.

However, there are applications where this kind of client caching produces annoying results: a time tracking tool may show a wrong clock-in state, or an SPA todo app may display an outdated list. In these cases, client caching should be disabled.

In order to prevent client caching, set a Cache-Control header of no-store. This tells _...

RubyMine: How to exclude single files

In RubyMine folders can be excluded from search, navigation etc. by marking it as excluded. You might sometimes wish to exclude single files, too. An example could be .byebug_history which is located in the project root directory.

Single files can be excluded by pattern in the Settings:

  1. In the Settings/Preferences dialog Ctrl+Alt+S, go to Project structure
  2. In the Exclude files field, type the masks that define the names of files and folders to be exclu...