How to make a cucumber test work with multiple browser sessions

Imagine you want to write a cucumber test for a user-to-user chat. To do this, you need the test to work with several browser sessions, logged in as separate users, at the same time.

Luckily, Capybara makes this relatively easy:

Scenario:

Scenario: Alice and Bob can chat
  Given Alice, Bob, and a chat session
  When I am signed in as "Alice"
    And I go to the chat
    And I am signed in as "Bob" [session: bob]
    And I go to the chat [session: bob]
    And I send the message "Hello, this is Alice!"
  Then I should see "Hello, this ...

Rails: Rest API post-mortem analysis

This is a personal post-mortem analysis of a project that was mainly build to provide a REST API to mobile clients.

For the API backend we used the following components:

  • Active Model Serializer (AMS) to serializer our Active Record models to JSON.
  • JSON Schema to test the responses of our server.
  • SwaggerUI to document the API.

It worked

The concept worked really good. Here are two points that were extraordinary compared to normal Rails project with many UI components:

  • Having a Rails application, that has no UI components (only...

Handling duplicate links with Capybara and Cucumber

Sometimes, you might have duplicate links on a page. Trying to click those links will by default cause Capybara to raise an Ambiguous match error.

If you do not care about which of those links are clicked, you can disable this errors by adding the following meta step:

When(/^(.*) \[allow ambiguous\]$/)do |step_text|
  prior_match_strategy = Capybara.match
  Capybara.match = :first
  step(step_text)
ensure
  Capybara.match = prior_match_strategy
end

Use it with

When I follow "a duplicate link" [allow ambiguous]

Capybara 'fill_in': Ambiguous match for different input names

When you have two inputs, where one contains the name of the other (eg. Name and Name with special treatment), Capybara's fill_in method will fail with the following message:

Ambiguous match, found 2 elements matching visible field "Name" that is not disabled (Capybara::Ambiguous)

You can force Capybara to match exactly what you are typing (which makes your tests better anyways) with match: :prefer_exact:

name = 'Name'
value = 'Bettertest Cucumberbatch'
fill_in(field, with: value, match: :prefer_exact)

Furthermore...

How to capture a screen-cast on Linux

Recording

SimpleScreenRecorder

I recommend simplescreenrecorder, it produces an adequate output with only a few clicks. The audio recording contained some static noises, but that might be caused by my microphone.

Recording only a single screen or fixed rectangle is supported. The video quality seems quite grained when using the default settings - I found that using the MKV container, H.264 codec, "0" constant rate factor and "veryslow" preset results in the best video quality.

###...

Geordi 2.7.0 released

  • Fixed #68: The "cucumber" command now fails early when @solo features fail.
  • Added: The "setup" command now prints the db adapter when prompting db credentials.
  • Fixed #71: When used without staged changes, the "commit" command will print a warning and create an empty commit. Any arguments to the command are forwarded to Git.
  • Fixed: The "commit" command will not print the extra message any more.
  • Added: The "commit" command prints a (progre...

Pattern: Disabling a certain feature in tests

There is a kind of features in web applications that hinder automated integration tests. Examples include cookie consent banners or form captchas. Clearly, these should be disabled so you do not have to explicitly deal with them in each and every test (like, every test starting with accepting the cookies notice). On the other hand, they must be tested as well.

A good feature disabling solution should therefore meet these requirements:

  • The feature is generally disabled in tests. A test does not need to do anything manually.

  • It is *...

Can I Email: Check what styling email clients support

The french Tilt Studio built a caniuse clone for email clients.

Note that while checking styling support helps using (or not using) certain features, it cannot substitute for checking the actual rendering in real clients. Make sure you follow Designing HTML Emails.

Linux, Arial and Helvetica: Different font rendering in Firefox and Chrome

When text renders differently in Firefox and Chrome, it may be caused by a font alias that both browsers handle differently.

Situation

A machine running Linux, and a website with the Bootstrap 3 default font-family: "Helvetica Neue", Helvetica, Arial, sans-serif.

Issue

Anti-aliasing and kerning of text looks bad in Firefox. Worse, it is rendered 1px lower than in Chrome (shifted down).

Reason

Firefox resolves "Helvetica" to an installed ["TeX Gyre Heros", which is its Ghostscript clone](https://www.fontsquirrel.com/fonts/...

Capybara: Execute asynchronous JavaScript

Capybara provides execute_script and evaluate_script to execute JavaScript code in a Selenium-controlled browser. This however is not a good solution for asynchronous JavaScript.

Enter evaluate_async_script, which allows you to execute some asynchronous code and wait until it finishes. There is a timeout of a couple of seconds, so it will not wait forever.

Use it like this:

page.evaluate_async_script(<<~JS)
  let [done] = arguments
  doSomethingAsynchronous().then(() => {
    done() // call this to indicate we're done
  })
J...

Email validation regex

There is a practical short list for valid/invalid example email addresses - Thanks to Florian L.! The definition for valid emails (RFC 5322) can be unhandy for some reasons, though.

Since Ruby 2.3, Ruby's URI lib provides a built-in email regex URI::MailTo::EMAIL_REGEXP. That's the best solution to work with.

/\A[a-zA-Z0-9.!\#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[...

WProofreader: How to manually enable for a WYSIWYG editor instance (with CKeditor 4 example)

WProofreader is a spelling and grammar checking tool that integrates with textareas and numerous WYSIWYG editors.
While it usually activates automatically, depending on your application, it may fail to boot.

In my case, an application was using CKEditor 4 and programmatically activated CKEditor. WProofreader's autoSearch logic failed to hook into that for some reason.

You can choose not to use its autoSearch feature, but explicitly enable WProofreader.
Here is a guide for CKEditor 4. It should apply to other WYSIWYG editors as well.

1...

Integrating or upgrading makandra-rubocop

Introduction

Most of the time it is a tedious task to apply a code style guide to an existing code base as there are likely to be a lot of conflicts. At makandra we are using makandra-rubocop to have code style checks. Here is some advice on how to add makandra-rubocop efficiently.

Note

RubyMine by default has a Rubocop inspection with rules that we don't always agree with. We recommend replacing this with makandra-rubocop or disabling the inspection.
...

How to enable Chromedriver logging

When using Chrome for Selenium tests, the chromedriver binary will be used to control Chrome. To debug problems that stem from Selenium's Chrome and/or Chromedriver, you might want to enable logging for the chromedriver itself. Here is how.

Option 1: Use Selenium::WebDriver::Service

In your test setup, you may already have something like Capybara::Selenium::Driver.new(@app, browser: :chrome, options: ...), especially when passing options like device emulation.

Similar to options, simply add an extra key service and pass an inst...

Using CSS transitions

CSS transitions are a simple animation framework that is built right into browsers. No need for Javascript here. They're supported by all browsers.

Basic usage

Transitions are used to animate the path between to property values. For example, to let the text color fade from red to green on hover, the following SASS is used (shorthand syntax):

.element
  color: red
  transition: color .1s
  
  &:hover
    color: green

This tells the browser "whenever the color of an .element changes...

Rails: Do not load frameworks you don't need

Rails is split into a large number of (sub-) frameworks.

The most important and central of those are

  • activesupport (extends the Ruby standard library)
  • activerecord / activemodel (ORM for Rails)
  • actionview / actionpack (controller / views)
  • actionmailer (sends mails)

However, there are also some more situational frameworks included, such as

  • actioncable (real time communications using websockets)
  • actionmailbox (receives mails)
  • actiontext (support for WYSIWYG text editor)
  • activejob (background jobs)
  • activestorage (file uplo...

Restore changes, even from deleted files, with RubyMines "Local History"-Feature

Sometimes, due to git or other "accidents", important files get deleted or overwritten.

At a state when even Ctrl+Z doesn't work anymore, you maybe can rescue your files with RubyMines "Local History"-Feature!

To do this try the following:

  • If the file got deleted, recreate a new empty file with the same name on the exact same place
  • Open that file in the editor
  • Go to RubyMine and click on VCS -> Local History -> Show History
  • In the now open window, you should see all greater changes made to the File, even before it got deleted/temp...

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

Git: Apply a diff

git apply allows you to apply a diff onto your HEAD. Most often you can achieve the same result with a rebase & merge.

Example:

master                commit1 - commit3
feature-branch                \ commit2 - commit4
git checkout feature-branch
git reset --hard commit3
git diff ..commit4 | git apply
master                commit1 - commit3
feature-branch                          \ Unstaged commit 2 & 4

You can also [create a patch and apply it afterwards](https://makandracards.com/makandra/2521-git-how-to...

Capybara: Quick checking for element presence (without retries or timeout)

Element finding is a central feature of Capybara. Since #find is normally used to get elements from the current page and interact with them, it's a good thing that some Capybara drivers (e.g. Selenium) will wait an amount of time until the expected element shows up. But if Capybara cannot #find it at all, you'll get an error.

if page.find('.that-element')
  # Do something
else
  # Never happens because #find raises
end

In order to simply check whether an element is present, without errors raised, you can use #has_css?. It...

Adding Jasmine JavaScript specs to a Webpack(er) project

The goal is to get Jasmine specs running in a Rails project using Webpacker, with the browser based test runner. Should be easily adaptable to a pure Webpack setup.

Image

Step 1: Install Jasmine

yarn add jasmine-core

Step 2: Add two separate packs

Since we do not want to mix Jasmine into our regular Javascript, we will create two additional packs. The first only contains Jasmine and the test runner. The second will contain our normal application code and the specs themselves.

We cannot...

How to make RubyMine aware of Cucumber steps defined in gems

If your Ruby project includes a gem like Spreewald that comes with some external step definition, RubyMine does not know about them by default and will highlight the step as an undefined reference:

Image

To link these external step definitions to RubyMine, add the corresponding gems to your RubyMine-Settings:

  • Go to Settings (ctrl + alt + s)
  • Go to Languages and Frameworks
  • Go to Cucumber
  • There, add your gem (e.g "spreewald") via the little "+" from the b...

Katapult EOL

Katapult was an endeavor to dramatically speed up starting a new Rails application. However, it turned out to save less time than expected, while requiring more time for maintenance than anticipated. Since its benefits fell too low, we have decided to not continue developing Katapult.

You can still use Katapult for generating ready-to-run applications with model CRUD, authentication and all of Katapult's features, but the rapid development of the web will quickly render the generated code antiquated. Nevertheless, its architecture may remai...

Selenium may break with ChromeDriver 75+

When you update your ChromeDriver to version 75 or beyond, you might get w3c errors in your tests.

For example, reading the browser console for errors no longer works, and page.driver.browser.manage.logs.get(:browser) will raise an error like "undefined method `log' for #<Selenium::WebDriver::Remote::W3C::Bridge:0x000055903f307aa8>".

Add options.add_option('w3c', false) to your Selenium configuration (e.g. features/support/selenium.rb) and you should be back to normal:

Capybara.register_driver :selenium do |app|
  options ...