Ruby: Referencing global variables with the built-in English library
tl;dr
Don't forget
require 'English'
if you use a named global such as$LAST_MATCH_INFO
. Otherwise this could result in an annoying bug.
With Ruby's build-in library English you can reference global variables with an english name. This makes you code easier to read and is also suggested by Rubocop's Style/GlobalVars cop.
Example before:
if 'foo' =~ /foo/
puts $~[1] # => foo
end
Example af...
How to use git fixup
Using git fixup helps you to speed up appending changes further back in the git history of your feature branch.
Example:
git commit --fixup aabbcc # Create a commit with the message "fixup! Commit message of aabbcc"
git rebase -i --autosquash master
It would be nice if you could use this feature without the -i
flag, but until now it seems not to be possible. Read more about our recommended git workflow for feature branches.
Also have a look at [git shortcut to use git fixup](https://makandracards.com/makand...
Five years of "Today I Learned" from Josh Branchaud
The linked GitHub repository is a bit like our "dev" cards deck, but groomed from a single person (Josh Branchaud). It includes an extensive list of over 900 TILs on many topics that might be interesting for most of us. (e.g. Ruby, Rails, Git, Unix..)
Ruby
Here is an excerpt of all the Ruby TILs that were new to me. I encourage you to take your time to skim over the original list as well!
-
Assoc For Hashes
- `Hash#ass...
Test-Driven Development with integration and unit tests: a pragmatic approach
Test-Driven Development (TDD) in its most dogmatic form (red-green-refactor in micro-iterations) can be tedious. It does not have to be this way! This guide shows a pragmatic approach with integration and unit tests, that works in practice and improves on productivity.
Advantages
- No added effort: tests need to be written anyway.
- Test heads serve as todo lists. You'll always know what is finished and what is left to do.
- Big tasks are broken down into smaller tasks that can be processed one by one.
- You will not forget a test.
- You...
How to use Simplecov to find untested code in a Rails project with RSpec and Cucumber
Simplecov is a code coverage tool. This helps you to find out which parts of your application are not tested.
Integrating this in a rails project with rspec, cucumber and parallel_tests is easy.
-
Add it to your Gemfile and bundle
group :test do gem 'simplecov', require: false end
-
Add a
.simplecov
file in your project root:SimpleCov.start 'rails' do # any custom configs like groups and filters can be here at a central place enable_cov...
Cucumber's table diffing does not play nice with Spreewald's `patiently do`
Turns out, Cucumber::MultilineArgument::DataTable#diff!
caches some stuff. Code of the following form will not work as intended:
Then('some table should look like') do |expected_table|
patiently do
actual_table = calculate_actual_table
expected_table.diff!(actual_table) # not actually patient, will keep failing if it failed the first time
end
end
Instead, simply use
expected_table.dup.diff!(actual_table)
Video transcoding: Web and native playback overview (April 2020)
Intro
Embedding videos on a website is very easy, add a <video>
tag to your source code and it just works. Most of the time.
The thing is: Both the operating system and Browser of your client must support the container and codecs of your video. To ensure playback on every device, you have to transcode your videos to one or more versions of which they are supported by every device out there.
In this card, I'll explore the available audio and video standards we have right now. The goal is to built a pipeline that...
How to write good code comments
Code comments allow for adding human readable text right next to the code: notes for other developers, and for your future self. You can imagine comments as post-its (or sometimes multi-sheet letters ...) on real-world objects like cupboards, light switches etc.
As always, with power comes responsibility. Code comments can go wrong in many ways: they may become outdated, silently move away from the code they're referring to, restate the obvious, or just clutter files.
Good Comments
Here are some simple rules to keep your comments help...
Capybara: How to find a hidden field by its label
To find an input with the type hidden, you need to specify the type hidden
:
find_field('Some label', type: :hidden)
Otherwise you will see an exception :
find_field('Some label')
# => Capybara::ElementNotFound: Unable to find field "Some label" that is not disabled`.
Note: Usually you don't need to check the input of hidden fields in an integration test. But e.g. waiting for a datepicker library to write the expected value to this field before continuing the test, which prevents flaky tests, is a valid use case.
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...