View
Repeats

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

```ruby
gem 'webpacker', '~> 4.x' # check if 4.x is still cu…

Repeats

Capybara/Selenium: evaluate_script might freeze your browser, use execute_script

In a nutshell: Do not use evaluate_script. Use execute_script instead!


Capybara gives you two different methods for executing Javascript:

page.evaluate_script("$('input').focus()")
page.execute_script("$('input').focus()")

While you can use both, the first line (with evaluate_script) might freeze your Firefox window for 10 seconds.

The reason is that evaluate_script will always return a result. The return value will be converted back to Ruby objects, which in case of complex objects (e.g. a jQuery collection) is *ver…

Repeats

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 wil…

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…

Repeats

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…
Repeats

Cucumber: Clear localStorage after each scenario

Capybara clears cookies before each scenario, but not other client-side data stores. If your app is using localStorage or sessionStorage, contents will bleed into the next scenario.

Use this hook to remove all site data after each scenario:

After do
  if Capybara.current_driver == :selenium && !Capybara.current_url.starts_with?('data:')
    page.execute_script <<-JAVASCRIPT
      localStorage.clear();
      sessionStorage.clear();
    JAVASCRIPT
  end
end

cucumber_factory: How to keep using Cucumber 2 Transforms in Cucumber 3

Cucumber up to version 2 had a neat feature called Step Argument Transforms which was dropped in favor of Cucumber 3 ParameterTypes. While I strongly encourage you to drop your legacy Transforms when upgrading to Cucumber 3, it might not always be possible due to their different design.
This is a guide on how to keep the exact same functionality of your old Transforms while writing them in the style of new `Paramet…

Repeats

Sass: Do not use comments between selector definitions

Sass lets you easily specify multiple selectors at once like this:

.some-block
  &.has-hover,
  &:hover
    outline: 1px solid red

This will add a red outline on either real hover or when the has-hover class is present. However, adding a comment will void the definition of that line:

.some-block
  &.has-hover, // From hoverable.js <-- DON'T
  &:hover
    outline: 1px solid red

… will simply drop the &.has-hover part.

Heads up: Capybara 3's text matchers no longer squish whitespace by default

Until Capybara 2, node finders that accept a text option were able to find nodes based on rendered text, even if it spans over multiple elements in the HTML. Imagine a page that includes this HTML:

<div class='haystack'>
  Hi!
  <br>
  Try to match me.
</div>

Even though the text is separated by a <br> tag in the HTML, it is matched until Capybara 2 which used to "squish" text prior to the comparison.

```ruby
# Capyabara 1 or 2
page.find(…

Some hints on upgrading to Unpoly 0.60.0

Unpoly 0.60.0 removed the jQuery dependency to improve performance (see Hennings talk about Javascript without jQuery). I upgraded one of our applications which used a lot of JavaScript with Unpoly compilers and jQuery and want to mention some aspects I had trouble with:

Use up.$compiler as a first step

up.compiler now yields a native DOM element instead of jQuery element. In order to get the old behavior, use up.$compiler. This is u…

Cucumber: Inspecting the Chrome download folder to test file downloads with Selenium

We already have some approaches on how to test file downloads withe selenium. Nonetheless here is another approach, which inspects the Chrome download folder. This way you do not need a separate logic on whether a file is served from a controller or a public path. The DownloadHelpers might also be re-used for reading e.g. a PDF file and checking its content.

Note: The step below will override a [spreewald step](https://gith…

Better compression for /boot partition

If you struggle with a /boot partition that is too small for updates, and you are too intimidated by the way to resize your /boot partition, there might be an easier fix:

It is possible to configure a better compression algorithm for the images in /boot. To do this, edit /etc/initramfs-tools/initramfs.conf and change the existing line to

COMPRESS=xz

Then rebuild the images using

sudo update-initramfs -u -k all

If you get an error during the last step, please immediately get help, because otherwise…

When reading model columns during class definition, you must handle a missing/empty database

When doing some meta-programming magic and you want to do something for all attributes of a class, you may need to access connection or some of its methods (e.g. columns) during class definition.

While everything will be fine while you are working on a project that is in active development, the application will fail to boot when the database is missing or has no tables. This means that Raketasks like db:create or db:migrate fail on a freshly cloned project.

The reason is your environment.rb which is loaded for Raketasks and calls…

Migration from the Asset Pipeline to Webpacker

This is a short overview of things that are required to upgrade a project from the Asset Pipeline to Webpacker. Expect this upgrade to take a few days even the diff is quite small afterwards.

Preparations

1. Find all libraries that are bundled with the asset pipeline. You can check the application.js and the application.css for require and import statements. The source of a library is most often a gem or a vendor directory.
2. Find an working example for each library in the application and write it down.
3. Find out the ver…

Linked content

How to doubleclick in Selenium

Put the attached file into features/support/.

Example usage:

When /^I open the task named "(.+?)"$/ do |task_name|
  task = page.all('.task').detect do |t|
    t.find('.label').text.downcase == task_name.downcase
  end
  
  task.double_click
end

Note: only Selenium understands doubleclicks.\ Credits: the attached Capybara issue discussion.

Repeats

Custom error pages in Rails 3.2+

Starting with Rails 3.2, there is a nicer way to display custom error pages (i.e. "page not found") that does not interfere with ExceptionNotifier. (I'm not sure about Airbrake et al.)

José Valim has posted this on his blog, here is a slightly more verbose rundown:

  1. Register your own app as the application responsible for showing error pages by adding

    config.exceptions_app = self.routes
    

    to your config/application.rb.

  2. Add rout…

Repeats

How to tackle complex refactorings in big projects

Sometimes huge refactorings or refactoring of core concepts of your application are necessary for being able to meet new requirements or to keep your application maintainable on the long run. Here are some thoughts about how to approach such challenges.

Break it down

Try to break your refactoring down in different parts. Try to make tests green for each part of your refactoring as soon as possible and only move to the next big part if your tests are fixed. It's not a good idea to work for weeks or months and wait for ALL puzzle pieces to…

Repeats

Getter and setter functions for Javascript properties

Javascript objects can have getter and setter functions that are called when a property is read from or written to.

For example, if you'd like an object that has a virtual person.fullName attribute that dynamically composes person.firstName and person.lastName:

```
var person = {

firstName: 'Guybrush',

lastName: 'Threepwood',

get fullName() {
return this.firstName + " " + this.lastName;
},

set fullName(name) {
var parts = name.split(" ");
this.firstName = parts[0];
this.lastName = parts[1];
}

};
```…

This website uses cookies to improve usability and analyze traffic.
Accept or learn more