Monday, October 26, 2015

Debugging Capybara Poltergeist tests in Rails

I made the switch from selenium webdriver to poltergeist on my capybara tests when the suite started taking 20 minutes to run. (For my process of getting the test suite under control, check out my previous post.) While poltergeist has definitely been a boon, it can sometimes be hard to debug because I can’t physically see the page. That’s where this tip comes in handy, stolen from the Quickleft blog:

Find the Port Address and Pause the Test 
Sometimes I just want to see what's going on in the browser. Although save_and_open_page gives you some idea of what's going on, you can't really click around, because the page it gives you is static and lacking assets. To dig into what's going on, I like to use a trick I learned from my mentor, Mike Pack. 
Just above the broken line in your test, add these two lines of code. Note that you have to have pry installed in your current gemset or specified in the Gemfile for this to work. 
puts current_url
require 'pry'; binding.pry 
Run the specs, and when they pause, copy the url and port number from the test output. 
Open your browser and paste the address into the window. Voila! You're now browsing your site in test mode!

Thanks again to the Quickleft folks for this cool tip - it’s one of five tricks for less painful testing.

Monday, October 19, 2015

Device Emulators all up in your browser

File this one under the "n00b" tag.

For checking responsiveness on mobile, Chrome (and probably Firefox) has some sweet device emulators.

Go to Developer Tools, then click the little phone icon in the far left of the Developer Tools nav
and it will let you select whatever device to see how the current page looks.

Wow. Much responsive. Very browser.


Monday, October 12, 2015

URL Encoding and Silly Safari

I have a web app that also acts as an API for an iOS, and I ran into a tricky situation. One of my models on the web app takes a URL as input, and it validates it using the validates_url gem. However, some URLs when visited from within the iOS app would give a Webkit error and show as invalid.

After some head scratching, it turned out that those URLs had encoding issues that were handled fine by all modern browsers except Safari, the default browser on iOS. For example, something with curly brackets like "http://www.example.com?ID={12345}" would work in most browser but not in Safari/iOS.

To get around this, in addition to using validates_url, I had to escape each URL during validation using URI.escape(url). The above URL would then become "http://www.example.com?ID={12345}". (Notice that the left curly bracket changed to %7B, the right turned to %7D - check out this HTML URL Encoding Reference for details)

But wait, there’s more!

It turns out that on subsequent saves, the URL would be escaped again, and it wouldn’t recognize the %7B and %7D as encoding, it would just see the % sign as an invalid character needing escape. So, on the second save, the same URL would be transformed again into "http://www.example.com?ID=%7B12345%7D". Notice the “25” inserted in there twice?

The fix ended up being something that reads very strange and seems unnecessary, but that works perfectly:

URI.escape(URI.unescape(url))

So, if a URL is already escaped, it unescapes it first, then re-escapes it. If the URL is not escaped, then unescaping it does nothing, then it gets escaped as it should.

If there’s a better way to do this, I haven’t found it, and am open to suggestions.

Tuesday, October 6, 2015

Refactoring using guard clauses

This post is almost purely about code style, but it’s an approach to coding and refactoring that I just found and really enjoy for its simplicity and readability.

The secret sauce to this approach is called a guard clause.

Say I have a method that I’m writing where I want to return one thing is a condition is true, another thing if it’s false. The way I used to write the code is exactly how I wrote that sentence:

def do_something_conditionally(fact)
    if fact == true
        fact
    else
        false
    end
end

Pretty standard, right? Now check out the same example with a guard clause:

def do_something_conditionally(fact)
    return false unless fact == true
    fact
end

We saved a couple lines of code, which is nice (although I could’ve saved more turning the conditional into ternary (fact == true ? fact : false)). However, the big gain from doing it this way is that it’s easier to read. Disagree?

It may help to have a more complex example, perhaps using nested conditionals:

def account_type
    if has_problems?
        type = "problems"
        if is_past_due?
            type = "past due"
            if is_weeks_past_due?
                type = "delinquent"
            end
        end
    else
        type = "normal"
    end
    type
end

…and now with guard clauses:

def account_type
    return "delinquent" if is_weeks_past_due?
    return "past due" if is_past_due?
    return "problems" if has_problems?
    "normal"
end

We’ve saved more lines of code, this time something we could not have easily change to ternary, and it’s harder to argue that this isn’t more readable now.

If all of that isn’t convincing enough, check out the quasi-official Ruby Style Guide, because it also recommends using guard clauses when possible.