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