Cheat Sheet for the modern DOM API
See the attached link for a useful overview of modern (and classic) DOM API methods, like matches
, contains
, append
, cssText
, etc.
You will still need to look up some documentation, e.g. on how to modify a ClassList
, but it's still better than browsing interfaces and superclasses of Element
on MDN without knowing what to look for.
When coming from jQuery, also see the card on JavaScript without jQuery. This card includes a link to [You Don't Need jQuery](https://github.com/nefe/You-Dont-Need-jQuery/blob/maste...
Threads and processes in a Capybara/Selenium session
TLDR: This card explains which threads and processes interact with each other when you run a Selenium test with Capybara. This will help you understand "impossible" behavior of your tests.
When you run a Rack::Test (non-Javascript) test with Capybara, there is a single process in play. It runs both your test script and the server responding to the user interactions scripted by your test.
A Selenium (Javascript) test has a lot more moving parts:
- One process runs your test script. This is the process you...
Capybara: Testing file downloads
Download buttons can be difficult to test, especially with Selenium. Depending on browser, user settings and response headers, one of three things can happen:
- The browser shows a "Save as..." dialog. Since it is a modal dialog, we can no longer communicate with the browser through Selenium.
- The browser automatically downloads the file without prompting the user. For the test it looks like nothing has happened.
- The browser shows a binary document in its own window, like a PDF. Capybara/Selenium freaks out because there is no HTML docum...
Passive event listeners may speed up your scroll and touch events
Scroll and touch event listeners tend to be computationally expensive as they are triggered very often. Every time the event is fired, the browser needs to wait for the event to be processed before continuing - the event could prevent the default behavior. Luckily there is a concept called passive event listeners which is supported by all modern browsers.
Below are the key parts quoted from WICG's explainer on passive event listeners. See [this demo video](https://www.youtube.com/watch?v=NPM6172...
Error handling in DOM event listeners
When an event listener on a DOM element throws an error, that error will be silenced and not interrupt your program.
In particular, other event listeners will still be called even after a previous listener threw an error. Also the function that emitted the event (like element.dispatchEvent()
or up.emit()
) will not throw
either.
In the following example two handlers are listening to the foo
event. The first handler crashes, th...
Testing for XSS in Markdown Fields
If you render markdown from user input, an attacker might be able to use this to inject javascript code into the source code of your page.
The linked github page is a collection of common markdown XSS payloads which is handy for writing tests.
Producing arbitrary links:
[Basic](javascript:alert('Basic'))
[Local Storage](javascript:alert(JSON.stringify(localStorage)))
[CaseInsensitive](JaVaScRiPt:alert('CaseInsensitive'))
[URL](javascript://www.google.com%0Aalert('URL'))
[In Quotes]('javascript:alert("InQuotes")')
Using onload...
Bug in Chrome 56+ prevents filling in fields with slashes using selenium-webdriver/Capybara
There seems to be a nasty bug in Chrome 56 when testing with Selenium and Capybara: Slashes are not written to input fields with fill_in
. A workaround is to use javascript / jquery to change the contents of an input field.
Use the following code or add the attached file to your features/support/
-directory to overwrite fill_in
.
module ChromedriverWorkarounds
def fill_in(locator, options = {})
text = options[:with].to_s
if Capybara.current_driver == :selenium && text.include?('/')
# There is a nasty Bug in Chrome ...
Things you probably didn’t know you could do with Chrome’s Developer Console
Collection of useful tools in the Chrome JavaScript console.
Make the whole page editable
This is not special to Chrome, but still a clever thing:
document.body.contentEditable=true
Taking time
You can easily measure the time on the console with named timers:
console.time('myTime'); // Start timer
console.timeEnd('myTime'); // End timer and print the time
Reference previously inspected elements (from the Elements panel)
Variables $0
, $1
, ... $n
reference the nth-last inspected Element. $0
...
How to add esbuild to the rails asset pipeline
This are the steps I needed to do to add esbuild to an application that used the vanilla rails asset pipeline with sprockets before.
Preparations
- update Sprockets to version 4
- add a
.nvmrc
with your preferred node version (and install it) - add gems
jsbundling-rails
andforeman
to yourGemfile
:gem 'jsbundling-rails' group :development, :test do gem 'foreman' # ... end
bundle install
- run
bin/rails javascript:install:esbuild
in a console to prepare esbuild. - run `yarn instal...
HTTP headers can only transport US-ASCII characters safely
HTTP header values must only contain low-ASCII (7-bit) characters for safe transport. From RFC 7230:
Historically, HTTP has allowed field content with text in the ISO-8859-1 charset [ISO-8859-1], supporting other charsets only through use of [RFC2047] encoding. In practice, most HTTP header field values use only a subset of the US-ASCII charset [USASCII]. Newly defined header fields SHOULD limit their field values to US-ASCII octets.
If you need to transport 8-bit+ characters (e.g...
Using CSS transitions
CSS transitions are a simple animation framework that is built right into browsers. No need for Javascript here. They're supported by all browsers.
Basic usage
Transitions are used to animate the path between to property values. For example, to let the text color fade from red to green on hover, the following SASS is used (shorthand syntax):
.element
color: red
transition: color .1s
&:hover
color: green
This tells the browser "whenever the color
of an .element
changes...
RubyMine: Efficiently filtering results in the "Finder" overlay
RubyMine comes with a nice way to grep through your project's files: The finder (ctrl + shift + f
). Don't be discouraged about the notice 100+ matches in n+ files
if your searched keyword is too general or widely used in your project.
RubyMine comes with a few ways to narrow down the resulting list, don't hesitate to apply those filters to speed up your search. Your keybinding might vary based on your personal settings.
File mask (alt + k
)
If you already know the file extension of your ...
Livereload + esbuild
Getting CSS (and JS) live reloading to work in a esbuild / Rails project is a bit of a hassle, but the following seems to work decently well.
We assume that you already use a standard "esbuild in Rails" setup, and have an esbuild watcher running that picks up your source code in app/assets
and compiles to public/assets
; if not change the paths below accordingly.
Basic idea
We will
- use the
guard-livereload
gem as the livereload server (which send updates to the browser), - use the
livereload-js
npm package in the browser to con...
Capybara will not find links without an href attribute
Capybara will fail to find <a>
tags that are missing an href
attribute. This will probably happen to you every now and then on JavaScript-heavy applications.
An example would be an AngularJS application where the following HTML actually works. [1]
<a ng-click="hello()">Hello</a>
Capybara will fail to find that link, even though looking it up via the DOM shows it:
>> find_link("Hello")
Capybara::ElementNotFound: Unable to find link "Hello"
>> find("a").text
=> "Hello"
To make find_link
and click_link
work, ...
The TCF 2.0 (Tranparency and Consent Framework) standard, and what you should know about it
The Interactive Advertising Bureau (IAB) is a European marketing association which has introduced a standard how advertising can be served to users in line with the General Data Protection Regulation (GDPR). This standard is called the TCF 2.0 (Transparency and Consent Framework). If you want to integrate any kind of advertising into a website, chances are the advertising network will require your website to implement that standard. This is a very brief overview of what this means:
The basic idea in the TCF 2.0 ...
Chrome DevTools: DOM Breakpoints - Breakpoints on HTML Elements
tl;dr
In Chrome DevTools in the Elements tab or in Firefox in the Inspector tab you can right click on an element and choose Break on to debug changes related to this element.
Example
DOM Breakpoints can be quite useful to quickly find the JavaScript that is responsible for some (unexpected) behavior. You can use DOM Breakpoints for debugging subtree modifications, attribute modifications or node removal.
Here you can see a very simple example that shows what JavaScript lines are responsible for ...
sessionStorage: Per-window browser storage
All major browsers (IE8+, FF3.5+, Safari 4+, any Chrome) support sessionStorage
, a JavaScript storage object that
- survives page reloads and browser restores,
- but is different per new tab/window (in contrast to
localStorage
which is shared across all tabs).
MDN says:
The
sessionStorage
object is most useful for hanging on to temporary data that should be saved and restored if the browser is accidentally refreshed
Demo
Example usage:
VCR fails if the same request is triggered multiple times
Same requests are recorded only once in vcr. Replaying a test fails, if you trigger the same request multiple times. The error message is somehow confusing, as your cassette contains the request:
An HTTP request has been made that VCR does not know how to handle
If you want to allow to match a request multiple times, you need to configure this explicit with allow_playback_repeats: true. Some exa...
WYSIWYG with Action Text
Rails 6 includes a WYSIWYG editor, Action Text. It works out of the box quite well, but chances are that you want to add some custom functionality. This card contains some tips how to achieve this.
Setup
Basically, follow the guide in the Rails documentation. The automated script may not work with the way webpacker is configured in your project, but it should be easy to fix.
If you don't want the default c...
CSS & a11y: When hiding with opacity, also set visibility:hidden (transitions supported)
Elements can be hidden and shown by toggling the display
property. However, this is not animatable, so we often turn to opacity
. At opacity: 0
, the element is hidden, and with a nice transition
on that property, it can be faded in and out smoothly.
Yet, opacity
only hides visually, not technically: the element is still focusable and visible to screen readers. So, how can we fade an element while maintaining accessibility?
Enter visibility
. It also hides elements, bu...
Rails: Flagging all cookies as secure-only to pass a security audit
Why secure-only cookies used to be necessary
Cookies have an optional secure
flag. It tells the browser to not send the cookie for a non-https request.
It used to be important to activate the secure
flag even on sites that automatically redirect users from http://
to https://
. The reason was that most users will only enter a scheme-less domain like makandra.de
into their location bar, which will default to `http://m...
Jasmine: Use `throwUnless` for testing-library's `waitFor`
testing-library are widely used testing utilities libraries for javascript dependent frontend testing. The main utilities provided are query methods, user interactions, dom expectations and interacting with components of several frontend frameworks, which allows us to worry less about the details happening in the browser and focus more on user centric tests instead!
Some of the time you will find a necessity to use methods like [waitFor
](https://testing-library.com/docs/dom-testing-library/api-async/...
Efficiently add an event listener to many elements
When you need to add a event listener to hundreds of elements, this might slow down the browser.
An alternative is to register an event listener at the root of the DOM tree (document
). Then wait for events to bubble up and check whether the triggering element (event.target
) matches the selector before you run your callback.
This technique is called event delegation.
Performance considerations
Because you only register a single listener, registering is ...
In Chrome 121+ the now supported spec-compliant scrollbar properties override the non-standard `-webkit-scrollbar-*` styles
Up until Chrome 120, scrollbars could only be styled using the various -webkit-scrollbar-*
pseudo elements, e.g. to make the scrollbars have no arrows, be rounded, or with additional margin towards their container.
Starting with version 121, Chrome now also supports the spec-compliant properties scrollbar-width
and scrollbar-color
.
These allow less styling. You may only specify the track and thumb colors, and a non-specific width like auto
, thin
, or none
.