iconfu iconfu iconfu is the world's largest collection of free, open-source icons and it comes with a handy image editor, so you can tweak icons to suit your needs exactly or even draw your own from scratch
invert blue resize move up verbose drawmode lighter previews remove swap animator library library draw shift up make a copy large editor explorer your icon contract agreement tag

27 January 2010

It should have no missing translations!

I'm a big fan of rspec and of rails' I18n, and I don't like having to study yml translation files over and over to make sure every key has a translation in every language; so I wrote it_should_have_no_missing_translations to test my templates for missing translations.

Previously, I needed this for every template:

  it "should have no missing translations in fr" do
    I18n.locale = "fr"
    do_render
    response.should_not have_tag("span.translation_missing")
  end

  it "should have no missing translations in en" do
    I18n.locale = "en"
    do_render
    response.should_not have_tag("span.translation_missing")
  end

Where do_render knows how to render the template I'm testing. If you're like me, and I presume you are, you're thinking the duplication up there is a bit annoying and someone should do something about it. Well, here you go:

  it_should_have_no_missing_translations

You like? Obviously, it_should_have_no_missing_translations needs a bit of context, like an implementation of do_render, and any other setup you need. Here's the implementation, under the WTFPL. Copy it into your specs or make a helper out of it that you include in your spec, or publish it in a gem and become famous.

  def it_should_have_no_missing_translations
    INSTALLED_LANGUAGES.each do |lang|
      it "should not have translations missing in #{lang}" do
        I18n.locale = lang
        do_render
        response.should_not have_missing_translations
      end
    end
  end

have_missing_translations is defined thus:

  INSTALLED_LANGUAGES = [:en, :fr] unless defined?(INSTALLED_LANGUAGES)

  class TranslationsMissing
    def initialize(scope)
      @scope = scope
    end

    def matches? response
      if response.is_a? String
        root_node = HTML::Document.new(response, false, false).root
      else
        root_node = HTML::Document.new(response.body, false, false).root
      end
      m = @scope.css_select root_node, ".translation_missing"
      @missing_translations = []
      m.each do |mt|
        @missing_translations << mt.children.first
      end
      m.size > 0
    end

    def failure_message
      "expected that response would contain a translation_missing element, but it didn't"
    end

    def negative_failure_message
      "expected that response would contain no missing translations, but it contained these \n#{@missing_translations.join("\n")}"
    end
  end

  def have_missing_translations
    TranslationsMissing.new self
  end

0 comments:

Post a Comment