Capybara: A step for finding images with filename and extension
This cucumber step is useful for testing an image (looking at the src
of the image).
Then(/^I should see the image "([^"]*)"$/) do |filename_with_extension|
expect(page).to have_css("img[src*='#{filename_with_extension}']")
end
Then I should see the image "placeholder.png"
Outline: Read more about how to test a uploaded file here, e.g. file downloads.
How to debug Rails autoloading
ActiveSupport::Dependencies takes care of auto-loading any classes in development. This is usually useful, but when you run into issues with the Rails autoloader, you should take a look at what it's doing.
For me this was useful in an "exciting" case of auto-loading classes inside a thread which caused the application to stop responding.
Rails 4.x
ActiveSupport::Dependencies includes logging support. It is easy to use:
ActiveSupport::Dependencies.logger = Rails.logger
Rails 5+
[Logging support was removed](https://github...
Carrierwave: Deleting files outside of forms
TL;DR Use user.update!(remove_avatar: true)
to delete attachments outside of forms. This will have the same behavior as if you were in a form.
As you know, Carrierwave file attachments work by mounting an Uploader
class to an attribute of the model. Though the database field holds the file name as string, calling the attribute will always return the uploader, no matter if a file is attached or not. (Side note: use #present?
on the uploader to check if the file exists.)
class User < ApplicationRecord
mount :avatar, ...
RSpec: How to check that an ActiveRecord relation contains exactly these elements
To check which elements an ActiveRecord relation contains use the contain_exactly
matcher.
describe User do
let!(:admin) { create(:user, role: 'admin') }
let!(:customer) { create(:user, role: 'customer') }
subject(:users) { User.where(role: 'admin') }
# Recommended (The error output is most helpful)
it { expect(users).to contain_exactly(admin) }
# Other options
it { expect(users).to eq([admin]) }
it { expect(users.pluck(:id).to eq([admin.id]) }
end
In case you have an `ActiveRecord::AssociationRelati...
Rails and Postgres: How to test if your index is used as expected
This is a small example on how you can check if your Postgres index can be used by a specific query in you Rails application. For more complex execution plans it might still be a good idea to use the same path of proof.
1. Identify the query your application produces
query = User.order(:last_name, :created_at).to_sql
puts query
# => SELECT "users".* FROM "users" ORDER BY "users"."last_name" ASC, "users"."created_at" ASC
2. Add an index in your migration and migrate
add_index :users, [:last_name, :created_at]...
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...
Error during Rails 5 upgrade: Environment data not found in the schema
This error is raised because your old database does not have a configured environment yet, which Rails 5 enforces.
If this error occurs while migrating your parallel test databases, make sure to update the parallel_tests
gem first: current versions fix this. If you're still using Cucumber < v3, the latest version of parallel_tests
will be 2.18.0.
Writing a README for a project
Rails applications and ruby gems should have a README that gives the reader a quick overview of the project. Its size will vary as projects differ in complexity, but there should always be some introductory prose for a developer to read when starting on it.
Purpose
That's already the main purpose of a project README: Give a new developer a quick overview of the project. In sketching this outline, the README should notify the reader of any peculiarity he needs to know of.
Remember that in a few months, you'll be a kind of "new ...
How to use cookies with curl
When making requests using curl, no cookies are sent or stored by default.
However, you can tell curl to re-use cookies received earlier (or forge your own cookies).
There are 2 command line switches you need to use:
-
-c
will write cookies to a given file -
-b
will read cookies from a given file
Example
The remote server sets a "foo" cookie to value "bar". We tell curl to store them to a file at /tmp/cookies
using the -c
switch.
$ curl -c /tmp/cookies http://httpbin.org/cookies/set?foo=bar
You may look at the file, ...
Rails: Migration helper for inserting records without using models
You should avoid using application models in your migrations. But how else could you create records in a migration?
The most basic way is to write plain SQL, but since INSERT statements are no pleasant write for Rubyists, here is a simple wrapper:
Record creation helper for migrations
The helper method below takes a table name and a hash of attributes, which it inserts into the specified table. Copy it over to your migration and profit!
private
def insert_record(table, **attributes)
attributes.merge!...
CSS: Giving text lines a background-color (with configurable line padding and margin)
The gist is:
- wrap the text with a
span
- use
line-height
for the spacing between lines ("margin") - use
box-shadow
to control the line background size ("padding")
Example
span
box-shadow: 0 0 0 10px #fff
background-color: #fff
box-decoration-break: clone # Fix Firefox
line-height: 2.2
→ [jsfiddle](https://jsfiddle.net/2fmqgbh...
Jasmine: Mocking API requests in an Angular service spec
Situation: You want to write a spec for a function inside an Angular service. This function at some point makes an API request and acts upon response. Notably, your Angular app employs uiRouter, although it is not used nor actually required for this test.
Working test setup
# Capitalized expressions are intended to be replaced with YOUR values
describe 'SERVICE', ->
beforeEach ->
module 'MODULE'
module ($urlRouterProvider) ->
# Prevent uiRouter's initialization, i.e. do not sync the current URL
# with its r...
Firefox cancels any JavaScript events at a fieldset[disabled]
If you try to listen to events on elements that are nested inside a <fieldset disabled>
, Firefox will stop event propagation once the event reaches the fieldset. Chrome and IE/Edge will propagate events.
Since we often bind event listeners to document
this can be annoying.
You could solve it by...
- ...adding event listeners on elements themselves. Note that this is terrible when you have many elements that you'd register events for.
- ...adding event listeners on a container inside the
<fieldset>
, around your eleme...
HTML: Making browsers wrap long words
By default, browsers will not wrap text at syllable boundaries. Text is wrapped at word boundaries only.
This card explains some options to make browsers wrap inside a long word like "Donaudampfschifffahrt"
.
Option 1: hyphens CSS property (preferred)
Modern browsers can hyphenate natively. Use the hyphens CSS property:
hyphens: auto
There is also hyphens: none
(disable hyphenations even at ­
entities) and hyphens: manual
(hy...
HTTPie nice command line HTTP client
HTTPie consists of a single http command designed for painless debugging and interaction with HTTP servers, RESTful APIs, and web services
It easy to use and has very nice defaults and coloured output which makes it good for local testing.
Usage examples with curl equivalent:
# curl post
curl --data "foo=23&bar=42" https://example.org/blub
# httpie post
http https://example.org/blub foo=23 bar=42
# curl localhost
curl localhost:3000/users
# httpie localhost
http :3000/users
PostgreSQL: WITH Queries (Common Table Expressions)
PostgreSQL's Common Table Expressions (CTEs) can be used to extract sub-queries from bulky SQL statements into a temporary table to be referenced instead.
This is most useful to avoid ugly joins or sub-selects. CTEs can be used for SELECT
, INSERT
, UPDATE
or DELETE
.
Example (from the PostgreSQL docs):
WITH regional_sales AS (
SELECT region, SUM(amount) AS total_sales
FROM orders
GROUP BY region
), top_regions AS (
SELECT region
FROM regional_sales
WHERE total_sales > (SE...
PostgreSQL's OVERLAPS operator is not fully inclusive
PostgreSQL supports the SQL OVERLAPS
operator. You can use it to test if two date ranges overlap:
=> SELECT ('2001-02-16'::date, '2001-12-21'::date) OVERLAPS
('2001-12-20'::date, '2002-10-30'::date);
overlaps
--------
true
An important caveat is that the date ranges are defined as start <= time < end
. As such the later date is not included in the range:
=> SELECT ('2001-02-16'::date, '2001-12-21'::date) OVERLAPS
('2001-12-21'::date, '2002-10-30'::date);
overlaps
--------
false
Also compar...
chromedriver-helper gem in Gemfile might break you selenium tests (of other projects)
Summary: Don't add chromedriver-helper to the Gemfile
- the executables might break your tests in projects where
chromedriver-helper
is not in the Gemfile - developers with different chrome versions will have problems using the same
chromedriver-helper
version
Background
If you install the chromedriver-helper
gem, but don't have it in you Gemfile, your selenium tests might fail with:
Selenium::WebDriver::Error::WebDriverError: unable to connect to chromedriver 127.0.0.1:9515
The reason is that chromedriver-helper
ov...
Cucumber: Identifying slow steps that drag down your test speed
In most projects I know, Cucumber test suite speed is not an issue. Of course, running 350 features takes its time, but still each test for itself is reasonably fast. There is nothing you can do to fundamentally speed up such a test (of course, you should be using parallel_tests).
However, in projects that go beyond clicking around in a web GUI and checking results, there might be various measures to speed things up. Katapult tests for example could be sped up more than 4 times by re...
Turning off VCR when stubbing with Webmock
Sometimes when working with VCR you still want to use webmock. Since VCR hooks into webmock and fails when an unknown request is happening, you have to turn it off in order to use webmock like you are used to. Here is how to do this in rspec.
RSpec.configure do |config|
config.around do | example |
if example.metadata[:turn_off_vcr]
VCR.turn_off!
example.run
VCR.turn_on!
else
example.run
end
end
end
Rails + Sidekiq::Web: Configuration for wildcard session cookies
When you're using Sidekiq::Web
to monitor the Sidekiq status AND have your session cookie configured to a wildcard domain like .example.com
, you need to take an additional step to keep your cookies valid.
Issue
Sidekiq::Web
is mounted into your Rails application and will use the Rails session cookie for protection from CSRF attacs. While it somehow figures out the cookie name, it does NOT respect cookie configuration like a custo...
Webservice to test and inspect requests
Requestb.in is a webservice that gives you a temporary URL you can use to test request. The page will automatically record and display the latest web request made to it.
How to install packages from newer Ubuntu releases
We're usually running Ubuntu LTS versions. Sometimes newer hardware requires packages from more recent Ubuntu releases that only come with 6 months of support. If there is really no other way, it's possible to install packages from later Ubuntu releases
Caution: Pay really close attention to what you're doing. Depending on the package, this process may require upgrading a lot of dependencies, possibly breaking the system! You really should not do this unless you've carefully calculated the impact on your system
Preparation
First,...
JavaScript: Testing the type of a value
Checking if a JavaScript value is of a given type can be very confusing:
- There are two operators
typeof
andinstanceof
which work very differently. - JavaScript has some primitive types, like string literals, that are not objects (as opposed to Ruby, where every value is an object).
- Some values are sometimes a primitive value (e.g.
"foo"
) and sometimes an object (new String("foo")
) and each form requires different checks - There are three different types for
null
(null
,undefined
andNaN
) and each has different rules for...