Testing CSS @imports

January 24, 2009 · 1 min read

A while back I wrote a script to check that @imported files actually exist in CSS stylesheets. I've since turned that into a proper set of RSpec examples for our test suite. Drop the code into something like spec/views/stylesheets/import_spec.rb and you'll catch broken imports before they reach production.

require File.dirname(__FILE__) + '/../../spec_helper'

describe "Stylesheet" do
  stylesheet_root = File.expand_path(RAILS_ROOT + '/public')
  stylesheets = Dir[File.join(stylesheet_root, "**", "*.css")]

  stylesheets.each do |stylesheet|
    describe stylesheet do
      it "should not @import files that don't exist" do

        missing_imports = []
        imports = File.read(stylesheet).split(/\n|\r/).grep(/\@import url\((.*)\)/)
        imports.each do |import|
          desired_path = import.scan(/url\((["'\ ])?(.*)\1\)/).to_a.first.to_a.last
          desired_root = desired_path[0,1] == "/" ? stylesheet_root : File.dirname(stylesheet)
          filesystem_path = File.expand_path(File.join(desired_root, desired_path))
          if !File.exists?(filesystem_path)
            missing_imports << { :path => filesystem_path, :directive => import }
          end
        end

        if missing_imports.any?
          exception = []
          missing_imports.each do |import|
            exception << "Missing @import file (#{import[:path]}) required for #{import[:directive]}"
          end
          raise exception.join("\n")
        end
      end
    end
  end
end

It walks every CSS file under public/, extracts all @import url() directives, resolves each path (respecting both absolute and relative references), and fails the spec with a clear message if any imported file is missing. Simple, but it's saved us from deploying broken stylesheets more than once.

These posts are LLM-aided. Backbone, original writing, and structure by Craig. Research and editing by Craig + LLM. Proof-reading by Craig.