Chromedriver: Connect local chromedriver with docker
Debugging your integration tests, that run a headless Chrome inside a docker image, is tricky.
In many cases you can connect your Chrome to a remote docker container like docker-selenium, which should be the preferred way when you try to inspect a page within your integration test.
Otherwise you might be able to start your docker container with --net=host
and access your local chromedriver in the host address space host.docker.internal
.
If both options above don't work for you here is a...
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...
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...
Limitations you should be aware of when Internet Explorer 9 parses CSS files
Internet Explorer until version 9 has some limitations when parsing CSS files
Summarized, these are:
- Up to 31 CSS files or
<style>
tags per page. - Up to 4095 selectors per CSS file.
- Up to 3 nested @import rules
To test the selector limit for a specific browser, check this CSS selector limitation test website.
When you run into this issue, the following links might be helpful to fix the problem. The Idea is to split up the css ...
RSpec: Marking sections in long examples
RSpec examples can get quite long, especially in feature specs. This makes them hard to read & understand. Also, when executing them, it may take seconds to see any progress.
To improve this, I have successfully been using a little "step" helper in my tests. It marks semantic sections, structuring an example while improving documentation. When the test runs, each step prints its message (or a dot, depending on your formatter).
# spec/support/step_helper.rb
module StepHelper
# Use this helper to label groups of related actions in l...
Capistrano: exclude custom bundle groups for production deploy
Capistrano is by default configured to exclude the gems of the groups development
and test
when deploying to the stages production
and staging
. Whenever you create custom groups in your Gemfile
, make sure to exclude these, if they should not be deployed to the servers. The gems of these groups might not be loaded by rails, however, the deployment process will take longer as the gems will be downloaded and installed to the server.
e.g. to exclude the groups cucumber
and deploy
, add the following to `config/deploy/production.rb...
Pitfall: ActiveRecord callbacks: Method call with multiple conditions
In the following example the method update_offices_people_count
won't be called when office_id
changes, because it gets overwritten by the second line:
after_save :update_offices_people_count, :if => :office_id_changed? # is overwritten …
after_save :update_offices_people_count, :if => :trashed_changed? # … by this line
Instead write:
after_save :update_offices_people_count, :if => :office_people_count_needs_update?
private
def office_people_count_needs_update?
office_id_changed? || trashed_changed?
end
Or...
How to turn images into inline attachments in emails
Not all email clients support external images in all situations, e.g. an image within a link. In some cases, a viable workaround is to turn your images into inline attachments.
Note
Rails provides a simple mechanism to achieve this:
This documentation makes it look like you have to care about these attachments in two places. You have to create the attachment in t...
Geordi: How to rerun failed features
Geordi's cucumber
command has a --rerun
option that reruns failing tests the given number of times. Usage:
geordi cucumber path/to/features --rerun=2
geordi cucumber path/to/features -r2
Background and how to rerun manually
Cucumber will save a file tmp/parallel_cucumber_failures.log
containing the filenames and line number of the failed scenarios after a full test run. Normally you can say cucumber -p rerun
(rerun is a profile defined by default in config/cucumber.yml
) to rerun all failed scenarios.
Here are a few al...
Detect the current Rails environment from JavaScript or CSS
Detecting if a Javascript is running under Selenium WebDriver is super-painful. It's much easier to detect the current Rails environment instead.
You might be better of checking against the name of the current Rails environment. To do this, store the environment name in a data-environment
of your <html>
. E.g., in your application layout:
<html data-environment=<%= Rails.env %>>
Now you can say in a pi...
Heads up: RSpec-Mocks' #stub_const will define intermediate modules that have not been loaded yet
The issue: You are using stub_const
to change a constant value for your test.
stub_const "SomeClass::CONST", 'test'
All of a sudden, tests fail with undefined method 'some_method' for #<SomeClass:0x00000000101433a8>
.
The reason
When using stub_const before the Class containing the constant has been loaded, a module is automatically created with the name.
Since RSpec does no autoloading, it will create a SomeClass
module by itself. This is arguably a good idea.
As a workaround, use stub_const
in your Rails specs li...
SAML Single Logout (SLO)
There are two ways a logout in SAML can happen: Service Provider (SP) initiated and Identity Provider (IDP) initiated logout. I'll explain how to implement both flows with devise_saml_authenticatable
.
Note
SAML also supports a
SOAP
and anArtifact
binding to do this. This guide only refers toPOST
andRedirect
bindings.devise_saml_authenticatable
does not supportSOAP
andArtifact
bindings.
SP initiated logout (using the Redirect Binding)
When the user clicks on Logout
within the app, the app can trigger...
CarrierWave: Default Configuration and Suggested Changes
CarrierWave comes with a set of default configuration options which make sense in most cases. However, you should review these defaults and adjust for your project wherever necessary.
You will also find suggestions on what to change below.
Understanding the default configuration
Here is the current default config for version 2:
config.permissions = 0644
config.directory_permissions = 0755
config.storage_engines = {
:f...
When loading Yaml contents in Ruby, use the :freeze argument to deep-freeze everything
Ruby methods which load from a Yaml file, like YAML.safe_load
or YAML.safe_load_file
, support passing freeze: true
to deep-freeze the entire contents from the Yaml file.
This is available by default on Ruby 3.0 and newer. On older Rubies, you can install psych
3.2.0 or newer for :freeze
support.
As an example, consider the following Yaml file:
---
message:
- hello
- universe
foo:
bar:
baz: "example"
We can now load it as usual, but pass freeze: true
.
>> test = YAML.safe_load_file('example.yml', fre...
Mock the browser time or time zone in Selenium features
In Selenium features the server and client are running in separate processes. Therefore, when mocking time with a tool like Timecop, the browser controlled by Selenium will still see the unmocked system time.
timemachine.js allows you to mock the client's time by monkey-patching into Javascript core classes. We use timemachine.js in combination with the Timecop gem to synchronize the local browser time to the ...
Middleman configuration for Rails Developers
Middleman is a static page generator that brings many of the goodies that Rails developers are used to.
Out of the box, Middleman brings Haml, Sass, helpers etc. However, it can be configured to do even better. This card is a list of improvement hints for a Rails developer.
Gemfile
Remove tzinfo-data
and wdm
unless you're on Windows. Add these gems:
gem 'middleman-livereload'
gem 'middleman-sprockets' # Asset pipeline!
gem 'bootstrap-sass' # If you want to use Bootstrap
gem 'byebug'
gem 'capistrano'
gem 'capistrano-mid...
Some tips for upgrading Bootstrap from 3 to 4
Recently I made an upgrade from Bootstrap 3 to Bootstrap 4 in a bigger project. Here are some tips how to plan and perform such an upgrade. The effort will scale with the size of the project and its structure. If your stylesheets already follow strict rules, it may take less time to adapt them to the new version.
Preparation
There are several gems and libraries that works well with bootstrap or provide at least stylesheets/plugins to easily integrate the bootstrap theme. But very often they only work with specific version or are no long...
RSpec: How to turn off partial double verification temporarily
While verifying doubles in RSpec is a good default, it is limited in the amount of methods it actually is able to verify.
The background is that RSpec can't verify dynamically defined methods, which is a known issue for the usage of helper_method and also the reason why [RSpec >= 3.6](http://rspec.info/blog/2017/05/rspec-3-6-has-been-rel...
Configuring Git with .gitconfig
Basic configuration
Please keep this config simple. It should be a starting point for new developers learning Git.
[user]
name = Your Name
email = your.name@domain.com
[branch]
sort = -committerdate
[color]
ui = auto
[color "branch"]
current = yellow reverse
local = yellow
remote = green
[color "diff"]
whitespace = white reverse
meta = blue reverse
frag = blue reverse
old = red
new = green
[color "status"]
added = green
changed = yellow
untracked = cyan
[interactive]
singlekey = true # Do not requir...
Prefer using Dir.mktmpdir when dealing with temporary directories in Ruby
Ruby's standard library includes a class for creating temporary directories. Similar to Tempfile it creates a unique directory name.
Note:
- You need to use a block or take care of the cleanup manually
- You can create a prefix and suffix e.g.
Dir.mktmpdir(['foo', 'bar']) => /tmp/foo20220912-14561-3g93n1bar
- You can choose a different base directory than
Dir.tmpdir
e.g. `Dir.mktmpdir('foo', Rails.root.join('tmp')) => /home/user/rails_example/tmp/foo20220912-14...
Version 5 of the Ruby Redis gem removes Redis.current
Redis.current
will be removed without replacement in redis-rb
5.0.
Version 4.6.0 adds deprecation warnings for Redis.current
and Redis.current=
:
`Redis.current=` is deprecated and will be removed in 5.0.
If your application still uses Redis.current
, you can only fix it by no longer using it. Here is how.
Redis.new when you need it
You can easily instantiate a Redis
client when you need it.
There is probably already a constant like REDIS_URL
that you use to configure Sidekiq or similar. So just use that one.
``...
RubyMine: Adjust Code Templates
tl;dr
To adjust code templates in RubyMine, navigate to Settings -> Editor -> File and Code Templates.
Example
You can navigate to the test file of the currently open file with the shortcut Ctrl + T
. If no test file exists, you can generate a new test file. If you are not pleased with the output, you can adjust the related code template. To do this, open the project settings and navigate to Editor -> File and Code Templates -> Files. Now, choose your relevant file type and adjust the code template according ...
Rails: Looking up constants by their name string
TL;DR: Rails ships two methods to convert strings to constants, constantize
and safe_constantize
. Neither is safe for untrusted user input. Before you call either method you must validate the input string against an allowlist. The only difference between the two methods is that unresolvable constants raise an error with constantize
, but return nil
with safe_constantize
. If you validate the input string against an allowlist, an error should never happen.
Preventing Dangerous Lookups
Suppose an application uses eit...
RSpec: Leverage the power of Capybara Finders and Matchers for view specs
View specs are a powerful tool to test several rendering paths by their cases instead of using a more costing feature spec. This is especially useful because they become quite convenient when used with Capybara::Node::Finders and Capybara::RSpecMatchers. This allows to wirte view unit specs as you can isolate specific part...