Sunday, April 1, 2012

How to Unit Test a custom Rails Form Builder

I recently created my first custom Rails builder.  It was very easy to do.

First, create a class that inherits from ActionView::Helpers::FormBuilder and then you can either write your own methods or overwrite the built in text_field, check_box, radio_button, etc.
class MyFirstFormBuilder < ActionView::Helpers::FormBuilder
 ...
end

Then, when using a form you can specify the builder (or set your builder to be the default in your config file)
<% form_for @post, :builder => MyFirstFormBuilder do |f| %>
 ...
<% end %>

That's all great and well documented, but I had a hard time finding the best way to write automated tests for the builder.  I was looking for a way to write unit tests directly against this class, rather than relying on a view and controller and using the heavier functional test framework.  Here is how it is done:

require File.expand_path('../../test_helper',  __FILE__)

class MyFirstFormBuilderTest < ActionView::TestCase
  tests ActionView::Helpers::FormHelper

  def protect_against_forgery?
    false
  end

  test_error_messages_format_when_no_errors
    assert @post.valid?

    form_for(:advertiser, @post, :url => "/foo",
                                 :builder => MyFirstFormBuilder) do |f|
      concat f.error_messages
    end

    assert_dom_equal "<form action="/foo" method="post"></form>",
                     output_buffer
  end
end


The keys are:
1. Inherit your unit test from ActionView::TestCase
2. tests ActionView::Helpers::FormHelper is key to allow you to directly call helper methods that you normally would call from an ERB template file (such as form_for)
2b. I had to define protect_against_forgery? in order to call form_for
3. output_buffer is an accessor of ActionView::TestCase, which is an HTMLDocument object of the output
4. assert_dom_equal is handy to compare HTML output for equality (ignoring attribute order and single quotes versus double quotes)

Tuesday, January 31, 2012

Detect if object is empty in JavaScript

I recently ran across a scenario where a function of mine was returning an Object (also known as a hash in other languages such as Ruby), and I wanted to check in the caller whether the returned Object was empty or not. I did not care what the contents were, just needed special handling for the empty case.

If you are already using jQuery, then this is a handy function that was added in 1.4 that I was unaware of! isEmptyObject
var myHash = { };
jQuery.isEmptyObject( myHash ); // true
myHash['foo'] = 'bar';
jQuery.isEmptyObject( myHash ); // false

It takes a single parameter, which is your Object, and returns true or false. It even takes into account "inherited" properties through the prototype object.

Monday, January 23, 2012

Usability fail: similar dialogs, different actions

Since Flash 10, the upgrade experience is fairly streamlined, but the dialogs that appear have tripped me up on multiple occasions.  And yes, I stress multiple, because they have a point release every week it seems, and with my 3 virtual machines plus main machine I went through a stretch a few months ago that I felt like I was completing the upgrade wizard every day.  Finally I decided to save the steps and write about it because I feel it is so obviously confusing, and yet if you only go through the process once or maybe twice every few months you probably think nothing of it.

Here is the first dialog that pops after booting up Windows:


Now after clicking "Install" you get a loading progress bar as the new version downloads.  Then you get this dialog:

Notice anything similar?  For one, there's that same "Install" button in the lower right.. didn't I just click that? Why aren't you installed yet?  That's the first problem.  How about just do the install when I said so the first time.  But wait, there's more.  On the first dialog, the single checkbox was to stop reminding me about this update.  But when I proceed now I'm seeing a similar dialog, with similar calls to action, so my brain instinctively ignores the checkbox.  Try to click Install this time and you get a warning message that you didn't agree to the terms. Doh!

This is what I end up seeing for both dialogs:


Sunday, January 22, 2012

Website fail: invalid data

It's no secret that I do not like Cox Communications.  I am not a fan of monopolies in any industry (don't get me started about text message "packages" and voice plans by cell phone companies), and I hate how Cox can get away with anything because they are the only cable broadband provider in the area.

When I moved accounts with them they screwed up my online access pretty bad and had horrible error handling on their site.  But after the dust was settled and I could log in and view my bill, I was happy to see that my bill was in fact due 2011 years ago (also, this screenshot was taken in November, it wasn't even January).

Clearly a billing date was missing somewhere and the UI just rendered what it could (perhaps their DB default for billing date is 01-01-0001 if they have no bills on record). I wonder if Cox uses MySQL and has NO_ZERO_DATE set (gets set when in traditional mode).. otherwise why not use 0000-00-00 or null for the default, unset billing date?

While this isn't a great example... I find it interesting that the errors and data validation bugs that show up on sites can sometimes shed light into the technologies or development practices that are used by said company.  And often it's not pretty.

Tuesday, August 2, 2011

IE9 Flash not rendering when wmode is set to opaque or transparent

I have a Windows 7 64-bit installation, with IE9 and the latest version of Flash (10.3.181.34) installed.  I was not able to view most flash in webpages, even the "about flash" page on Adobe's site.

There is a long thread with various workarounds and solutions (which all were promised to be unnecessary once 10.3.181.16 was released), but it was not until the 3rd page that I found a hint which allowed me to fix the issue.

My solution:
  1. Go to IE9 > Tools > Internet Options > Advanced.
  2. Check the "Do not save encrypted pages to disk" option
  3. Restart IE9
  4. View http://www.adobe.com/software/flash/about/ and shake head at Adobe and Microsoft



This seems like the more secure option, so not sure why it wasn't set...hopefully this doesn't break something else in IE! I did not do further research on this specific option or why it was at all related to Flash rendering (and only flash that had wmode=opaque or wmode=transparent).  Sigh.