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
- Removed VNC test browser support for integration tests – Headless Chrome has
matured and is almost a drop-in replacement. Also, key binding issues have
increased with VNC and recent Linux.- Please use a headless Chrome setup https://makandracards.com/makandra/492109-capybara-running-tests-with-headless-chrome.
- You might also ...
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:
- In the Settings/Preferences dialog
Ctrl+Alt+S
, go to Project structure - In the Exclude files field, type the masks that define the names of files and folders to be exclu...
Carrierwave: Using a nested directory structure for file system performance
When storing files for lots of records in the server's file system, Carrierwave's default store_dir
approach may cause issues, because some directories will hold too many entries.
The default storage directory from the Carrierwave templates looks like so:
class ExampleUploader < CarrierWave::Uploader::Base
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
If you store files for 500k records, that store_dir
's parent directory will have 500k sub-directories which will cause some...
Debugging your Webpack build time with Speed Measure Plugin
If your Webpack build is slow, you can use the Speed Measure Plugin for Webpack to figure out where time is being spent.
Note that at time of writing, Webpack 5 seems unsupported. It works on Webpack 4, though.
Wire it into your application as described in the library's documentation:
- Hook into your environment file, e.g.
config/webpack/development.js
and instead of exporting your Webpackconfig
,...
When does Webpacker compile?
Webpack builds can take a long time, so we only want to compile when needed.
This card shows what will cause Webpacker (the Rails/Webpack integration) to compile your assets.
When you run a dev server
While development it is recommended to boot a webpack dev server using bin/webpack-dev-server
.
The dev server compiles once when booted. When you access your page on localhost
before the initial compilation, the page may load without assets.
The ...
Limiting GitLab CI runner to specific branches or events
Use rules to include or exclude jobs in pipelines.
Rules are evaluated in order until the first match. When a match is found, the job is either included or excluded from the pipeline, depending on the configuration. The job can also have certain attributes added to it.
rules replaces only/except and they can’t be used together in the same job. If you configure one job to use both keywords, the linter returns a key may not be used with rules error.
GitLab 12.3 introduced rules. You can use them in your .gitlab-ci.yml
in your proj...
Clean code: Avoiding short versions in command options
This card is a general reminder to avoid the short version of a command option in shared code. It's much easier to understand a command and search for an option when it's written out.
You can still use the short version of the options in your own terminal or in code snippets that are more useful when they are very compact. For the latter case you often see a description of the command options one line below e.g. in posts on stackoverflow.
Example good (in code):
/usr/bin/gpg --output password.txt --decrypt password.txt.gpg
...
How to generate and test a htpasswd password hash
Generate a password
htpasswd -Bn firstname.lastname
This will ask you for a password and use bcrypt (-B
, more secure) and print the output to stdout (-n
).
Check if password matches the hash
You'll first have to write the password hash to a file:
echo firstname.lastname:$2y$05$4JXxd2GM/J2...9c3KJmFS > htpass_test
Check, if it is correct:
htpasswd -v htpass_test firstname.lastname
You probably should not use the -b
switch to read the password from the command line as the password will then be visible...
How to push to Git without running CI on GitLab CI, GitHub Actions, or Travis CI
If a project ist configured to spawn CI runners for tests or deployment when pushing to the Repo, a habit of pushing WIP commits regularly may conflict with that.
Here are two solutions that allow you to keep pushing whenever you feel like it.
Special commit message
To skip a CI run, simply add [ci skip]
or [skip ci]
to your commit message. Example:
git commit -m "wip authentication [ci skip]"
Git push options (GitLab)
In addition to that, GitLab CI supports Git push options. Instead of changing your commit message, ...
Delivering Carrierwave attachments to authorized users only
Preparation
To attach files to your records, you will need a new database column representing the filename of the file. To do this, add a new migration (rails g migration <name>
) with the following content:
class AddAttachmentToNotes < ActiveRecord::Migration[6.0]
def change
add_column :notes, :attachment, :string
end
end
Don't forget to rename the class and change the column details to fit your purpose. Run it.
1) Deliver attachments through Rails
The first way is to store your Carrierwave attachments not ...
What does 100% mean in CSS?
The attached article examines what the percent unit (%
) is relative to in CSS
The article does a great job of visualizing the dependencies. The TLDR is:
Own property | % of |
---|---|
height |
parent height |
width |
parent width |
top |
parent height |
left |
parent width |
margin-top |
parent width |
margin-left |
parent width |
padding-top |
parent width |
padding-left |
parent width |
Ruby: How to convert hex color codes to rgb or rgba
When you have a hex color code, you can easily convert it into its RGB values using plain Ruby.
>> "#ff8000".match(/^#(..)(..)(..)$/).captures.map(&:hex)
=> [255, 128, 0]
You can use that to implement a simple "hex to CSS rgba value with given opacity" method:
def hex_color_to_rgba(hex, opacity)
rgb = hex.match(/^#(..)(..)(..)$/).captures.map(&:hex)
"rgba(#{rgb.join(", ")}, #{opacity})"
end
>> hex_color_to_rgba("#ff8000", 0.5)
=> "rgba(255, 128, 0, 0.5)"
If you need to support RGBA hex color codes,...
Online tool to convert tables between different formats
https://tableconvert.com/ is an online tool to convert tables between different formats (e.g. json, markdown, csv).
It also has a button to transpose a table ("rotate" it by 90 degree).
The tool can be handy if you have tests with large markdown tables for testing contents of a flat json structure or csv.
Please note that you should not use it with sensitive data (like all online tools in general).
Capybara: Preventing headless Chrome from freezing your test suite
We prefer to run our end-to-end tests with headless Chrome. While it's a very stable solution overall, we sometimes see the headless Chrome process freeze (or the Capybara driver losing connection, we're not sure).
The effect is that your test suite suddenly stops progressing without an error. You will eventually see an error after a long timeout but until then it will seem that your suite is frozen. If you're also using [capybara-screenshot](https:/...
Capybara: Preventing server errors from failing your test
When your Rails application server raises error, Capybara will fail your test when it clears the session after the last step. The effect is a test that passes all steps, but fails anyway.
Capybara's behavior will help you to detect and fix errors in your application code. However, sometimes your application will explode with an error outside your control. Two examples:
- A JavaScript library references a source map in its build, but forgets to package the source map
- CarrierWave cleans up an upload or cache file after the record was delet...
E-mail deliverability
When your application is open for public sign up and sends out transactional e-mails to a large number of users, e-mail deliverability becomes an issue.
E-mail providers work hard to eliminate spam and have put in place relatively tight checks what kinds of emails they will accept, and from whom. To that end we use tools like mail-tester.com to make our mails as acceptable as possible. Unfortunately, there will always be providers that reject our e-mails for some reason or other, sometimes outside of our control.
For exa...
Capybara: Pretending to interact with the document
Browsers blocks abusable JavaScript API calls until the user has interacted with the document. Examples would be opening new tab or start playing video or audio.
E.g. if you attempt to call video.play()
in a test, the call will reject with a message like this:
NotAllowedError: play() failed because the user didn't interact with the document first. https://goo.gl/xX8pDD
Workaround
To pretend document interaction in a test you can create an element, click on it, and remove the element again. This unblocks the entire JavaSc...