vendor/plugins/haml/test/sass/plugin_test.rb in radiant-0.9.1 vs vendor/plugins/haml/test/sass/plugin_test.rb in radiant-1.0.0.rc1

- old
+ new

@@ -3,24 +3,28 @@ require 'sass/plugin' require 'fileutils' class SassPluginTest < Test::Unit::TestCase @@templates = %w{ - complex script parent_ref import alt + complex script parent_ref import scss_import alt subdir/subdir subdir/nested_subdir/nested_subdir + options } + @@templates += %w[import_charset import_charset_ibm866] unless Haml::Util.ruby1_8? + @@templates << 'import_charset_1_8' if Haml::Util.ruby1_8? def setup FileUtils.mkdir tempfile_loc FileUtils.mkdir tempfile_loc(nil,"more_") set_plugin_opts - Sass::Plugin.update_stylesheets + update_all_stylesheets! reset_mtimes end def teardown clean_up_sassc + clear_callbacks FileUtils.rm_r tempfile_loc FileUtils.rm_r tempfile_loc(nil,"more_") end @@templates.each do |name| @@ -30,109 +34,231 @@ end def test_no_update File.delete(tempfile_loc('basic')) assert_needs_update 'basic' - Sass::Plugin.update_stylesheets + update_all_stylesheets! assert_stylesheet_updated 'basic' end def test_update_needed_when_modified touch 'basic' assert_needs_update 'basic' - Sass::Plugin.update_stylesheets + update_all_stylesheets! assert_stylesheet_updated 'basic' end def test_update_needed_when_dependency_modified touch 'basic' assert_needs_update 'import' - Sass::Plugin.update_stylesheets + update_all_stylesheets! assert_stylesheet_updated 'basic' + assert_stylesheet_updated 'import' end + def test_update_needed_when_scss_dependency_modified + touch 'scss_importee' + assert_needs_update 'import' + update_all_stylesheets! + assert_stylesheet_updated 'scss_importee' + assert_stylesheet_updated 'import' + end + + def test_scss_update_needed_when_dependency_modified + touch 'basic' + assert_needs_update 'scss_import' + update_all_stylesheets! + assert_stylesheet_updated 'basic' + assert_stylesheet_updated 'scss_import' + end + def test_full_exception_handling - File.delete(tempfile_loc('bork')) - Sass::Plugin.update_stylesheets - File.open(tempfile_loc('bork')) do |file| - assert_equal("/*\nSass::SyntaxError: Undefined variable: \"!bork\".\non line 2 of #{template_loc('bork')}\n\n1: bork\n2: :bork= !bork", file.read.split("\n")[0...6].join("\n")) + File.delete(tempfile_loc('bork1')) + update_all_stylesheets! + File.open(tempfile_loc('bork1')) do |file| + assert_equal(<<CSS.strip, file.read.split("\n")[0...6].join("\n")) +/* +Syntax error: Undefined variable: "$bork". + on line 2 of #{template_loc('bork1')} + +1: bork +2: :bork $bork +CSS end - File.delete(tempfile_loc('bork')) + File.delete(tempfile_loc('bork1')) end def test_nonfull_exception_handling old_full_exception = Sass::Plugin.options[:full_exception] Sass::Plugin.options[:full_exception] = false - File.delete(tempfile_loc('bork')) - assert_raise(Sass::SyntaxError) {Sass::Plugin.update_stylesheets} + File.delete(tempfile_loc('bork1')) + assert_raise(Sass::SyntaxError) {update_all_stylesheets!} ensure Sass::Plugin.options[:full_exception] = old_full_exception end def test_two_template_directories set_plugin_opts :template_location => { template_loc => tempfile_loc, template_loc(nil,'more_') => tempfile_loc(nil,'more_') } - Sass::Plugin.update_stylesheets + update_all_stylesheets! ['more1', 'more_import'].each { |name| assert_renders_correctly(name, :prefix => 'more_') } end def test_two_template_directories_with_line_annotations set_plugin_opts :line_comments => true, :style => :nested, :template_location => { template_loc => tempfile_loc, template_loc(nil,'more_') => tempfile_loc(nil,'more_') } - Sass::Plugin.update_stylesheets + update_all_stylesheets! assert_renders_correctly('more1_with_line_comments', 'more1', :prefix => 'more_') end - def test_merb_update - begin - require 'merb' - rescue LoadError - puts "\nmerb couldn't be loaded, skipping a test" - return + def test_doesnt_render_partials + assert !File.exists?(tempfile_loc('_partial')) + end + + def test_template_location_array + assert_equal [[template_loc, tempfile_loc]], Sass::Plugin.template_location_array + end + + def test_add_template_location + Sass::Plugin.add_template_location(template_loc(nil, "more_"), tempfile_loc(nil, "more_")) + assert_equal( + [[template_loc, tempfile_loc], [template_loc(nil, "more_"), tempfile_loc(nil, "more_")]], + Sass::Plugin.template_location_array) + + touch 'more1', 'more_' + touch 'basic' + assert_needs_update "more1", "more_" + assert_needs_update "basic" + update_all_stylesheets! + assert_doesnt_need_update "more1", "more_" + assert_doesnt_need_update "basic" + end + + def test_remove_template_location + Sass::Plugin.add_template_location(template_loc(nil, "more_"), tempfile_loc(nil, "more_")) + Sass::Plugin.remove_template_location(template_loc, tempfile_loc) + assert_equal( + [[template_loc(nil, "more_"), tempfile_loc(nil, "more_")]], + Sass::Plugin.template_location_array) + + touch 'more1', 'more_' + touch 'basic' + assert_needs_update "more1", "more_" + assert_needs_update "basic" + update_all_stylesheets! + assert_doesnt_need_update "more1", "more_" + assert_needs_update "basic" + end + + # Callbacks + + def test_updating_stylesheets_callback + # Should run even when there's nothing to update + assert_callback :updating_stylesheets, [] + end + + def test_updating_stylesheets_callback_with_individual_files + files = [[template_loc("basic"), tempfile_loc("basic")]] + assert_callback(:updating_stylesheets, files) {Haml::Util.silence_haml_warnings{Sass::Plugin.update_stylesheets(files)}} + end + + def test_updating_stylesheets_callback_with_never_update + Sass::Plugin.options[:never_update] = true + assert_no_callback :updating_stylesheets + end + + def test_updating_stylesheet_callback_for_updated_template + Sass::Plugin.options[:always_update] = false + touch 'basic' + assert_no_callback :updating_stylesheet, template_loc("complex"), tempfile_loc("complex") do + assert_callbacks( + [:updating_stylesheet, template_loc("basic"), tempfile_loc("basic")], + [:updating_stylesheet, template_loc("import"), tempfile_loc("import")]) end - - require 'sass/plugin/merb' - if defined?(MerbHandler) - MerbHandler.send(:define_method, :process_without_sass) { |*args| } - else - Merb::Rack::Application.send(:define_method, :call_without_sass) { |*args| } - end + end - set_plugin_opts + def test_updating_stylesheet_callback_for_fresh_template + Sass::Plugin.options[:always_update] = false + assert_no_callback :updating_stylesheet + end - File.delete(tempfile_loc('basic')) - assert_needs_update 'basic' - - if defined?(MerbHandler) - MerbHandler.new('.').process nil, nil - else - Merb::Rack::Application.new.call(::Rack::MockRequest.env_for('/')) + def test_updating_stylesheet_callback_for_error_template + Sass::Plugin.options[:always_update] = false + touch 'bork1' + assert_no_callback :updating_stylesheet + end + + def test_not_updating_stylesheet_callback_for_fresh_template + Sass::Plugin.options[:always_update] = false + assert_callback :not_updating_stylesheet, template_loc("basic"), tempfile_loc("basic") + end + + def test_not_updating_stylesheet_callback_for_updated_template + Sass::Plugin.options[:always_update] = false + assert_callback :not_updating_stylesheet, template_loc("complex"), tempfile_loc("complex") do + assert_no_callbacks( + [:updating_stylesheet, template_loc("basic"), tempfile_loc("basic")], + [:updating_stylesheet, template_loc("import"), tempfile_loc("import")]) end + end - assert_stylesheet_updated 'basic' + def test_not_updating_stylesheet_callback_with_never_update + Sass::Plugin.options[:never_update] = true + assert_no_callback :not_updating_stylesheet end - def test_doesnt_render_partials - assert !File.exists?(tempfile_loc('_partial')) + def test_not_updating_stylesheet_callback_for_partial + Sass::Plugin.options[:always_update] = false + assert_no_callback :not_updating_stylesheet, template_loc("_partial"), tempfile_loc("_partial") end + def test_not_updating_stylesheet_callback_for_error + Sass::Plugin.options[:always_update] = false + touch 'bork1' + assert_no_callback :not_updating_stylesheet, template_loc("bork1"), tempfile_loc("bork1") + end + + def test_compilation_error_callback + Sass::Plugin.options[:always_update] = false + touch 'bork1' + assert_callback(:compilation_error, + lambda {|e| e.message == 'Undefined variable: "$bork".'}, + template_loc("bork1"), tempfile_loc("bork1")) + end + + def test_compilation_error_callback_for_file_access + Sass::Plugin.options[:always_update] = false + assert_callback(:compilation_error, + lambda {|e| e.is_a?(Errno::ENOENT)}, + template_loc("nonexistent"), tempfile_loc("nonexistent")) do + Sass::Plugin.update_stylesheets([[template_loc("nonexistent"), tempfile_loc("nonexistent")]]) + end + end + + def test_creating_directory_callback + Sass::Plugin.options[:always_update] = false + dir = File.join(tempfile_loc, "subdir", "nested_subdir") + FileUtils.rm_r dir + assert_callback :creating_directory, dir + end + ## Regression def test_cached_dependencies_update FileUtils.mv(template_loc("basic"), template_loc("basic", "more_")) set_plugin_opts :load_paths => [result_loc, template_loc(nil, "more_")] touch 'basic', 'more_' assert_needs_update "import" - Sass::Plugin.update_stylesheets + update_all_stylesheets! assert_renders_correctly("import") ensure FileUtils.mv(template_loc("basic", "more_"), template_loc("basic")) end @@ -141,15 +267,22 @@ def assert_renders_correctly(*arguments) options = arguments.last.is_a?(Hash) ? arguments.pop : {} prefix = options[:prefix] result_name = arguments.shift tempfile_name = arguments.shift || result_name - expected_lines = File.read(result_loc(result_name, prefix)).split("\n") - actual_lines = File.read(tempfile_loc(tempfile_name, prefix)).split("\n") + expected_str = File.read(result_loc(result_name, prefix)) + actual_str = File.read(tempfile_loc(tempfile_name, prefix)) + unless Haml::Util.ruby1_8? + expected_str = expected_str.force_encoding('IBM866') if result_name == 'import_charset_ibm866' + actual_str = actual_str.force_encoding('IBM866') if tempfile_name == 'import_charset_ibm866' + end + expected_lines = expected_str.split("\n") + actual_lines = actual_str.split("\n") + if actual_lines.first == "/*" && expected_lines.first != "/*" - assert(false, actual_lines[0..actual_lines.enum_with_index.find {|l, i| l == "*/"}.last].join("\n")) + assert(false, actual_lines[0..Haml::Util.enum_with_index(actual_lines).find {|l, i| l == "*/"}.last].join("\n")) end expected_lines.zip(actual_lines).each_with_index do |pair, line| message = "template: #{result_name}\nline: #{line + 1}" assert_equal(pair.first, pair.last, message) @@ -168,31 +301,93 @@ if actual_lines.first == "/*" && expected_lines.first != "/*" assert(false, actual_lines[0..actual_lines.enum_with_index.find {|l, i| l == "*/"}.last].join("\n")) end end - def assert_needs_update(name) - assert(Sass::Plugin.stylesheet_needs_update?(name, template_loc, tempfile_loc), - "Expected #{template_loc(name)} to need an update.") + def assert_callback(name, *expected_args) + run = false + Sass::Plugin.send("on_#{name}") do |*args| + run ||= expected_args.zip(args).all? do |ea, a| + ea.respond_to?(:call) ? ea.call(a) : ea == a + end + end + + if block_given? + yield + else + update_all_stylesheets! + end + + assert run, "Expected #{name} callback to be run with arguments:\n #{expected_args.inspect}" end - def assert_doesnt_need_update(name) - assert(!Sass::Plugin.stylesheet_needs_update?(name, template_loc, tempfile_loc), - "Expected #{template_loc(name)} not to need an update.") + def assert_no_callback(name, *unexpected_args) + Sass::Plugin.send("on_#{name}") do |*a| + next unless unexpected_args.empty? || a == unexpected_args + + msg = "Expected #{name} callback not to be run" + if !unexpected_args.empty? + msg << " with arguments #{unexpected_args.inspect}" + elsif !a.empty? + msg << ",\n was run with arguments #{a.inspect}" + end + + flunk msg + end + + if block_given? + yield + else + update_all_stylesheets! + end end + def assert_callbacks(*args) + return update_all_stylesheets! if args.empty? + assert_callback(*args.pop) {assert_callbacks(*args)} + end + + def assert_no_callbacks(*args) + return update_all_stylesheets! if args.empty? + assert_no_callback(*args.pop) {assert_no_callbacks(*args)} + end + + def clear_callbacks + Sass::Plugin.instance_variable_set('@_sass_callbacks', {}) + end + + def update_all_stylesheets! + Haml::Util.silence_haml_warnings do + Sass::Plugin.update_stylesheets + end + end + + def assert_needs_update(*args) + assert(Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(*args), template_loc(*args)), + "Expected #{template_loc(*args)} to need an update.") + end + + def assert_doesnt_need_update(*args) + assert(!Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(*args), template_loc(*args)), + "Expected #{template_loc(*args)} not to need an update.") + end + def touch(*args) FileUtils.touch(template_loc(*args)) end def reset_mtimes - Dir["{#{template_loc},#{tempfile_loc}}/**/*.{css,sass}"].each {|f| File.utime(Time.now, Time.now - 1, f)} + Sass::Plugin::StalenessChecker.dependencies_cache = {} + atime = Time.now + mtime = Time.now - 5 + Dir["{#{template_loc},#{tempfile_loc}}/**/*.{css,sass,scss}"].each {|f| File.utime(atime, mtime, f)} end def template_loc(name = nil, prefix = nil) if name - absolutize "#{prefix}templates/#{name}.sass" + scss = absolutize "#{prefix}templates/#{name}.scss" + File.exists?(scss) ? scss : absolutize("#{prefix}templates/#{name}.sass") else absolutize "#{prefix}templates" end end @@ -221,16 +416,11 @@ :template_location => template_loc, :css_location => tempfile_loc, :style => :compact, :load_paths => [result_loc], :always_update => true, + :never_update => false, }.merge(overrides) - end -end - -module Sass::Plugin - class << self - public :stylesheet_needs_update? end end class Sass::Engine alias_method :old_render, :render