How to test print stylesheets with Cucumber and Capybara
A print stylesheet is easy to create. Choose a font suited for paper, hide some elements, done. Unfortunately print stylesheets often break as the application is developed further, because they are quickly forgotten and nobody bothers to check if their change breaks the print stylesheet.
This card describes how to write a simple Cucumber feature that tests some aspects of a print stylesheets. This way, the requirement of having a print stylesheet is manifested in your tests and cannot be inadvertedly removed from the code. Note that you can...
Flash-Free Clipboard for the Web
Unfortunately, Web APIs haven’t provided the functionality to copy text to the clipboard through JavaScript, which is why visiting GitHub with Flash disabled shows an ugly grey box where the button is supposed to be. Fortunately, we have a solution. The editor APIs provide document.execCommand as an entry point for executing editor commands. The "copy" and cut" commands have previously been disabled for web pages, but with Firefox 41, which is currently in Beta, and slated to move to release in mid-September, it is becoming available to Ja...
rails/turbolinks
Turbolinks makes following links in your web application faster. Instead of letting the browser recompile the JavaScript and CSS between each page change, it keeps the current page instance alive and replaces only the body and the title in the head.
This is similar to pjax, but instead of worrying about what element on the page to replace, and tailoring the server-side response to fit, we replace the entire body. This means that you get the bulk of the speed benefits from pjax (no recompiling of the JavaScript or CSS) without having to tail...
How to solve Selenium focus issues
Selenium cannot reliably control a browser when its window is not in focus, or when you accidentally interact with the browser frame. This will result in flickering tests, which are "randomly" red and green. In fact, this behavior is not random at all and completely depends on whether or not the browser window had focus at the time.
This card will give you a better understanding of Selenium focus issues, and what you can do to get your test suite stable again.
Preventing accidental interaction with the Selenium window
--------------------...
Jasmine: Testing AJAX calls that manipulate the DOM
Here is a Javascript function reloadUsers()
that fetches a HTML snippet from the server using AJAX and replaces the current .users
container in the DOM:
window.reloadUsers = ->
$.get('/users').then (html) ->
$('.users').html(html)
Testing this simple function poses a number of challenges:
- It only works if there is a
<div class="users">...</div>
container in the current DOM. Obviously the Jasmine spec runner has no such container. - The code requests
/users
and we want to prevent network interaction in our uni...
Draggabilly
Javascript library for drag'n'drop that seems to have more options than native HTML5 drag'n'drop.
They also claim to support "multi-touch", which would be awesome if it means that you can drag on touch devices.
Another library with similar aims is interact.js (Github).
They're pitching JavaScript drag and drop, resizing and multi-touch gestures with inertia and snapping for modern browsers (and also IE8+).
Dynamically uploading files to Rails with jQuery File Upload
Say we want …
- to create a
Gallery
that has a name andhas_many :images
, which in turn have a caption - to offer the user a single form to create a gallery with any number of images
- immediate uploads with a progress bar per image
- a snappy UI
Enter jQuery File Upload. It's a mature library that can do the job frontend-wise. On the server, we'll use Carrierwave, because it's capable of caching images.
(FYI, [here's how to do the u...
Waiting for page loads and AJAX requests to finish with Capybara
If you're using the Capybara webdriver, steps sometimes fail because the browser hasn't finished loading the next page yet, or it still has a pending AJAX request. You'll often see workarounds like
When I wait for the page to load
Then ...
Workarounds like this do not work reliably, will result in flickering tests and should be avoided. There is no known reliable way to detect if the browser has finished loading the page.
Solution
Instead you should wait until you can observe the result of a page load. E.g. if y...
Reverse-proxying web applications with Apache 2.4+
Note: Making a reverse proxy with nginx is much more straightforward.
A reverse proxy is a "man in the middle" server that tunnels requests to another server. You can use for things like:
- Expose a local service that you cannot directly reach over the internet
- "Change" the domain or path of a web application by rewriting them on the fly
- Instantly change servers that respond to a name or ...
How to: Use Ace editor in a Webpack project
The Ace editor is a great enhancement when you want users to supply some kind of code (HTML, JavaScript, Ruby, etc).
It offers syntax highlighting and some neat features like auto-indenting.
For Webpack 3+
Integrate as described in the documentation. For example load ace Editor like this:
function loadAceEditor() {
return import(/* webpackChunkName: "ace" */ 'ace-builds/src-noconflict/ace').then(() => {
return import(/* webpackChunkName: "ace" */ 'ace-builds/webpack-r...
AngularJS: How to force Content-Type on GET and DELETE requests
While you usually do not need a Content-Type
on GET request (which have a blank body), an external API may still force you to send one.
Angular's $http
service will strip that header when the request data (body) is blank. [1] This is possibly a misconception of RFC2616.
Here is how to send GET requests with a Content-Type
header in Angular.
Example
Consider this request:
$http({ me...
Manually uploading files via AJAX
To upload a file via AJAX (e.g. from an <input type='file'>
) you need to wrap your params in a FormData
object.
You can initialize a FormData
using the contents of a form:
var form = document.querySelector('form.my-form') // Find the <form> element
var formData = new FormData(form); // Wrap form contents
Or you can construct it manually, param by param:
var fileInput = document.querySelector('form input[type=file]');
var attachment = fileInput.files[0];
var f...
Test redirects to an external URL with Cucumber/Capybara
When a controller action redirects to an external URL (like http://somehost.com/some/path
) you will find that this is hard to test with Cucumber and Capybara:
- A non-Javascript Rack::Test scenario will just ignore the host and try to open
/some/path
in your local application - A Selenium test will actually follow the redirect, which you probably don't want either
There are two workarounds for this. You can use either, or a combination of both.
- Write a controller spec
Controller specs can test if a resp...
DOM API for jQuery users
General hints on the DOM
- the root of the DOM is
document
- custom elements inherit from
HTMLElement
. They need a-
(dash) in their name, e.g.<notification-box>
. - event listeners don't have event delegation à la
.on('click', cssSelector, handler)
Comparison
Action | jQuery | DOM API equivalent |
---|---|---|
Find descendant(s) by CSS selector | .find(selector) |
one: `.querySelector(selecto... |
Async/Await Will Make Your Code Simpler
Sometimes modern Javascript projects get out of hand. A major culprit in this can be the messy handling of asynchronous tasks, leading to long, complex, and deeply nested blocks of code. Javascript now provides a new syntax for handling these operations, and it can turn even the most convoluted asynchronous operations into concise and highly readable code.
How to disable auto-complete on login forms
Disabling auto-complete in login forms is probably a bad idea, since it encourages weak passwords.
If you are still forced to implement this (maybe due to legal or policy requirements), this is how:
Prevent browsers from saving the password in the first place. Disabling autocomplete does not improve security.
How to prevent password saving:
To prevent the browser from saving passwords (and usernames), you need to:
- copy username and password to hidden form fields before submitting the login form
- c...
Sticky table header with jQuery
When you want the table headers to always stay around (e.g. because that table is huuuge), use the code below.
Style
table.fixed_table_header{
position: fixed;
top: 0;
width: auto;
display: none;
border: none;
margin: 0;
}
Javascript
;(function($) {
$.fn.fixHeader = function() {
return this.each(function() {
var $table = $(this),
$t_fixed;
function init() {
$t_fixed = $table.clone();
$t_fixed.find('tbody').remove().end().addClass('fi...
Coffeescript: Caveat when cloning objects with fat-arrow methods
Coffeescript allows you to create classes whose methods are automatically bound to the correct this
. You can do this by using a fat arrow:
class Person
constructor: (name) ->
@name = name
sayHello: =>
alert("Hello, I am #{@name}")
An important caveat is that when you clone such an object, all of its methods are still bound to the original instance:
eve = new Person("Eve")
eve.sayHello() # => "Hello, I am Eve"
bob = _.clone(eve)
bob.name = "Bob"
bob.sayHello() # => "Hello, I am Eve"
I don't thin...
Run Chrome in a specific resolution or user agent with Selenium
When you want to test how an web-application reacts in a specific resolution, you can set up a specific Selenium driver for some tests:
Before('@chrome320x480') do
Capybara.current_driver = :chrome320x480
end
After('@chrome320x480') do
Capybara.use_default_driver
end
You can use either chromium or chrome beta (as of 2012.05 the Version "19.0.1084.41 beta" works), or any other member of the family. It only needs to supports the "--window-size" command-line switch. [See this list](http://peter.sh...
6 front-end techniques for Rails developers. Part I: From big ball of mud to separated concerns
Amazing guide how to divide a ball of Javascript spaghetti distinct separate layers (model, view, controller, backend adapter).
It does not use a Javascript framework.
hint.css - A tooltip library in CSS
A tooltip library that does not use Javascript. Works in IE9+.
This library (or the technique used by it) could be a great choice for projects with a lot of tooltips, which are hard to do fast with Javascript.
Tabs in Textarea Plugin for jQuery
This is a demo of the "Tabby" Javascript jQuery plugin to use tabs in regular textareas to make them suitable for in-browser coding of languages like HTML, CSS, Javascript, or your favorite server-side language. The idea is to be able to use a press of the TAB button or SHIFT+TAB to indent or outdent your code.
Using CSS3PIE cross-domain
Currently not possible as the linked .htc file contains JavaScript which is not explicitly called.
The developers are working on a pure JavaScript solution which will have some downsides but work across different domains.
jnicklas's capybara at master - GitHub
Capybara sets up some tags for you to use in Cucumber. Often you’ll want to run only some scenarios with a driver that supports JavaScript, Capybara makes this easy: simply tag the scenario (or feature) with @javascript: