Skip to content

Easy Integration of Minitest::Spec and VCR

12-Sep-11

I’m a big fan of MiniTest. I use it for basically all of my testing in Ruby. I’ve also started to use VCR to help with stubbing and recording HTTP requests during tests. In a nutshell, VCR lets hit the actual resource on the first run. VCR then records the results and replays them back on subsequent test runs. It really helps to speed up tests and isolate externals.

Recently, I had to integrate VCR with MiniTest::Spec. MiniTest by default runs tests in random order. Additionally, there is no after(:all) hook available in MiniTest. When integrating MiniTest with VCR, tests which would have otherwise been unaffected by order may now produce false failures due to VCR.

This is when I came up with a rather simple solution to have each test run in isolation and have their own specific cassette. At my top level describe block for each test file, I have a before block that sets up a VCR cassette for each expectation. Here’s the code for this solution (and a gist):

describe "Something" do
  before do
    # __name__ defined in MiniTest::Unit::TestCase
    VCR.insert_cassette __name__
  end

  after do
    VCR.eject_cassette
  end
end

Now every single it or specify block that makes one or more HTTP requests will generate and use it’s own cassette. Granted, this solution is somewhat verbose in the amount of cassettes that are generated. I feel however, this is a reasonable trade off for its sheer simplicity!

Update: I added this solution and some more general information about MiniTest to VCR’s wiki.

nginx Custom Maintenance Page without Redirects

08-Aug-11

For BreakBase, we use nginx as a reverse proxy to our app server. When we deploy updates, the upstream app server is temporarily offline. Rather than have nginx respond with the default “502 Bad Gateway” page, we replace it with our own maintenance page. Additionally, we also need to make sure our maintenance page does not redirect the user so their requested URI stays the same. That way when the upstream server is back online, a simple refresh will take the user to their originally requested page.

Below is the configuration for our maintenance page:

error_page 502 =200 @maintenance;
location @maintenance {
    root /path/to/maintenance;
    try_files $uri $uri/ /index.html =503;
}

There are a lot of things going on in this configuration. First off, we are using a named location with an error_page directive to “catch” the 502 error. Secondly, the =200 in this directive is used to set the response code to 200. This is done so browsers properly render the page as well as any CSS or images that are included.

Finally, we use the try_files directive in order to first try and serve the requested file (for CSS and images). If these files are not found, it will then try and serve an index.html file. If for some reason index.html is not available, we fallback to the default 503 error page which is more appropriate than the 502 page.

HTML5 Data Attributes for Pylons Webhelpers

15-Jul-11

HTML5 data attributes let developers store bits of meta-data directly within markup. They are an incredibly useful tool and I would highly recommend checking out the first few hits on Google for more details on exactly how they are used.

While working on BreakBase, I can across a bit of an issue with creating data attributes using Pylons’ Webhelper tags. Attributes are generally assigned in Webhelper tags using Python kwargs. This is an issue since data attributes require a dash character, which results in invalid Python code. Additionally, we use Mako templates so using an inline dict object is not an option since it will clash with the Mako delimiters.

Thus, I created a really simple helper that we can use in the meanwhile until data attribute support is added to Webhelpers directly. Here the helper method definition (and a github gist):

def data_attrs(**kwargs):
    attrs = {}
    for suffix in kwargs:
        key = "data-%s" % suffix
        attrs[key] = kwargs[suffix]
    
    return attrs

To use this helper, simply do the following:

${ h.link_to("link text", "/some/url", **h.data_attrs(some="data", available="here")) }

Which will produce the following valid markup:

<a href="/some/url" data-some="data" data-available="here">link text</a>

Introducing jQuery.whiny.js

11-Jul-11

We’ve all done something like this:

$('#id').text('new text');

And wondered why the code wasn’t working only to find out the selector was wrong. jQuery.whiny.js attempts to solve this problem by altering the jQuery library so the jQuery() method will create a console warning if an empty jQuery object returned.

In the above example, if ‘#id’ returned an empty jQuery object you’d see the following console warning:

jQuery was called with a selector of '#id' and returned an empty object

Please note, this is only for dev purposes. To get the jQuery.whiny.js, head over to the github project. Additionally, the name of this script was inspired by “whiny nil” from Ruby on Rails.

jQuery Selector Injection

28-Jun-11

First off, this type of issue is more theoretical than anything.

jQuery allows you create HTML elements on the fly via the jQuery() method. Creating new HTML elements using this technique is common in the jQuery world since it results in more readable, jQuery-esque code.

Potential client-side code injection issues can arise if malicious input is passed to this method. Consider the following example:

$("<img src='/' onerror=alert('xss');>");

This will result in client-side code execution (mainly an alert displaying the string ‘xss’). Nevertheless, it is possible to execute arbitrary client-side code via this vector. To see this in action, check my overly contrived demo\proof-of-concept available here.

Now you should be asking yourself, what does this mean for me as a jQuery developer? In reality, not a whole lot. The main point here is that developers should always be mindful of what input is passed to the jQuery() method. Much like how developers need to be mindful of user-input in order to prevent other XSS issues and DB-level injections.

The bottom-line: never trust user-input.

Update: This issue has now been partly addressed by jQuery 1.6.3. Refer to bug #9521 for details on the fix. In short, #id are prioritized over <tag> selectors.

The issue in general however, is still possible with selectors that are not #id based. Take a look at my second overly contrived proof-of-concept here which uses a .class selector instead of an #id one.