2006-11-28 20:33:22 +00:00
#!/usr/bin/env ruby
2008-06-08 09:54:36 -07:00
require File . dirname ( __FILE__ ) + '/../test_helper'
2006-12-04 02:47:37 +00:00
require 'sass/plugin'
2008-06-08 09:54:36 -07:00
require 'fileutils'
2006-11-28 20:33:22 +00:00
class SassPluginTest < Test :: Unit :: TestCase
2007-05-03 09:04:20 +00:00
@@templates = %w{
2009-12-31 17:55:45 -08:00
complex script parent_ref import scss_import alt
2007-05-03 09:04:20 +00:00
subdir / subdir subdir / nested_subdir / nested_subdir
2010-01-20 20:30:14 -08:00
options
2007-05-03 09:04:20 +00:00
}
2006-12-04 02:47:37 +00:00
2006-11-28 20:33:22 +00:00
def setup
2008-07-14 11:32:08 -07:00
FileUtils . mkdir tempfile_loc
FileUtils . mkdir tempfile_loc ( nil , " more_ " )
2007-11-17 19:55:26 +00:00
set_plugin_opts
2010-04-10 16:32:14 -07:00
update_all_stylesheets!
2010-01-23 16:06:31 -08:00
reset_mtimes
2006-11-28 20:33:22 +00:00
end
2007-08-28 05:33:57 +00:00
2006-12-03 23:17:45 +00:00
def teardown
2009-04-15 19:35:13 -07:00
clean_up_sassc
2010-01-23 15:37:39 -08:00
clear_callbacks
2008-07-14 11:32:08 -07:00
FileUtils . rm_r tempfile_loc
FileUtils . rm_r tempfile_loc ( nil , " more_ " )
2006-12-03 23:17:45 +00:00
end
2006-11-28 20:39:33 +00:00
2009-07-19 14:56:11 -07:00
@@templates . each do | name |
define_method ( " test_template_renders_correctly ( #{ name } ) " ) do
assert_renders_correctly ( name )
end
2006-11-28 20:39:33 +00:00
end
2007-08-28 05:33:57 +00:00
2006-11-28 20:39:33 +00:00
def test_no_update
2006-12-04 02:47:37 +00:00
File . delete ( tempfile_loc ( 'basic' ) )
2009-12-22 09:55:18 -08:00
assert_needs_update 'basic'
2010-04-10 16:32:14 -07:00
update_all_stylesheets!
2009-12-24 12:06:51 -08:00
assert_stylesheet_updated 'basic'
2006-12-04 02:47:37 +00:00
end
2007-08-28 05:33:57 +00:00
2007-09-02 01:48:25 +00:00
def test_update_needed_when_modified
2010-01-23 16:06:31 -08:00
touch 'basic'
2009-12-22 09:55:18 -08:00
assert_needs_update 'basic'
2010-04-10 16:32:14 -07:00
update_all_stylesheets!
2009-12-24 12:06:51 -08:00
assert_stylesheet_updated 'basic'
2007-09-02 01:48:25 +00:00
end
def test_update_needed_when_dependency_modified
2010-01-23 16:06:31 -08:00
touch 'basic'
2009-12-22 09:55:18 -08:00
assert_needs_update 'import'
2010-04-10 16:32:14 -07:00
update_all_stylesheets!
2009-12-24 12:06:51 -08:00
assert_stylesheet_updated 'basic'
2009-12-31 17:55:45 -08:00
assert_stylesheet_updated 'import'
end
def test_update_needed_when_scss_dependency_modified
2010-01-30 15:47:04 -08:00
touch 'scss_importee'
2009-12-31 17:55:45 -08:00
assert_needs_update 'import'
2010-04-10 16:32:14 -07:00
update_all_stylesheets!
2009-12-31 17:55:45 -08:00
assert_stylesheet_updated 'scss_importee'
assert_stylesheet_updated 'import'
end
def test_scss_update_needed_when_dependency_modified
2010-01-30 15:47:04 -08:00
touch 'basic'
2009-12-31 17:55:45 -08:00
assert_needs_update 'scss_import'
2010-04-10 16:32:14 -07:00
update_all_stylesheets!
2009-12-31 17:55:45 -08:00
assert_stylesheet_updated 'basic'
assert_stylesheet_updated 'scss_import'
2007-09-02 01:48:25 +00:00
end
2007-11-17 19:55:26 +00:00
def test_full_exception_handling
2009-09-13 19:27:56 -07:00
File . delete ( tempfile_loc ( 'bork1' ) )
2010-04-10 16:32:14 -07:00
update_all_stylesheets!
2009-09-13 19:27:56 -07:00
File . open ( tempfile_loc ( 'bork1' ) ) do | file |
2009-09-13 20:34:59 -07:00
assert_equal ( <<CSS.strip, file.read.split("\n")[0...6].join("\n"))
2009-09-13 20:28:56 -07:00
/ *
2010-03-06 16:08:04 -08:00
Syntax error : Undefined variable : " $bork " .
2009-09-13 20:34:59 -07:00
on line 2 of #{template_loc('bork1')}
2009-09-13 20:28:56 -07:00
1 : bork
2010-03-27 18:10:51 -07:00
2 : :bork $bork
2009-09-13 20:28:56 -07:00
CSS
2006-12-22 06:59:38 +00:00
end
2009-09-13 19:27:56 -07:00
File . delete ( tempfile_loc ( 'bork1' ) )
2006-12-04 02:47:37 +00:00
end
2007-02-06 05:24:13 +00:00
2007-11-17 19:55:26 +00:00
def test_nonfull_exception_handling
2009-12-24 12:00:46 -08:00
old_full_exception = Sass :: Plugin . options [ :full_exception ]
2007-11-17 19:55:26 +00:00
Sass :: Plugin . options [ :full_exception ] = false
2007-02-06 05:24:13 +00:00
2009-09-13 19:27:56 -07:00
File . delete ( tempfile_loc ( 'bork1' ) )
2010-04-10 16:32:14 -07:00
assert_raise ( Sass :: SyntaxError ) { update_all_stylesheets! }
2009-12-24 12:00:46 -08:00
ensure
Sass :: Plugin . options [ :full_exception ] = old_full_exception
2007-02-06 05:24:13 +00:00
end
2008-06-19 16:10:50 -07:00
def test_two_template_directories
2008-07-14 11:32:08 -07:00
set_plugin_opts :template_location = > {
template_loc = > tempfile_loc ,
template_loc ( nil , 'more_' ) = > tempfile_loc ( nil , 'more_' )
}
2010-04-10 16:32:14 -07:00
update_all_stylesheets!
2008-08-09 09:43:15 -07:00
[ 'more1' , 'more_import' ] . each { | name | assert_renders_correctly ( name , :prefix = > 'more_' ) }
2008-06-19 16:10:50 -07:00
end
2007-08-28 05:33:57 +00:00
2008-08-09 09:44:40 -07:00
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_' )
}
2010-04-10 16:32:14 -07:00
update_all_stylesheets!
2008-08-09 09:44:40 -07:00
assert_renders_correctly ( 'more1_with_line_comments' , 'more1' , :prefix = > 'more_' )
end
2007-11-17 19:55:26 +00:00
def test_merb_update
begin
require 'merb'
rescue LoadError
puts " \n merb couldn't be loaded, skipping a test "
return
end
require 'sass/plugin/merb'
2009-01-09 10:58:30 +01:00
if defined? ( MerbHandler )
MerbHandler . send ( :define_method , :process_without_sass ) { | * args | }
else
Merb :: Rack :: Application . send ( :define_method , :call_without_sass ) { | * args | }
end
2007-11-17 19:55:26 +00:00
set_plugin_opts
File . delete ( tempfile_loc ( 'basic' ) )
2009-12-22 09:55:18 -08:00
assert_needs_update 'basic'
2007-11-17 19:55:26 +00:00
2009-01-09 10:58:30 +01:00
if defined? ( MerbHandler )
MerbHandler . new ( '.' ) . process nil , nil
else
Merb :: Rack :: Application . new . call ( :: Rack :: MockRequest . env_for ( '/' ) )
end
2007-11-17 19:55:26 +00:00
2009-12-24 12:06:51 -08:00
assert_stylesheet_updated 'basic'
2007-11-17 19:55:26 +00:00
end
2007-08-28 05:33:57 +00:00
def test_doesnt_render_partials
assert ! File . exists? ( tempfile_loc ( '_partial' ) )
end
2010-05-10 21:37:57 -07:00
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
2010-01-23 15:37:39 -08:00
# 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 " ) ] ]
2010-04-10 16:32:14 -07:00
assert_callback ( :updating_stylesheets , files ) { Haml :: Util . silence_haml_warnings { Sass :: Plugin . update_stylesheets ( files ) } }
2010-01-23 15:37:39 -08:00
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
2010-01-23 16:09:11 -08:00
touch 'basic'
2010-01-23 15:37:39 -08:00
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
end
def test_updating_stylesheet_callback_for_fresh_template
Sass :: Plugin . options [ :always_update ] = false
assert_no_callback :updating_stylesheet
end
def test_updating_stylesheet_callback_for_error_template
Sass :: Plugin . options [ :always_update ] = false
2010-01-23 16:09:11 -08:00
touch 'bork1'
2010-01-23 15:37:39 -08:00
assert_no_callback :updating_stylesheet
end
2010-01-23 16:25:01 -08:00
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
def test_not_updating_stylesheet_callback_with_never_update
Sass :: Plugin . options [ :never_update ] = true
assert_no_callback :not_updating_stylesheet
end
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
2010-01-23 17:01:19 -08:00
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 ,
2010-03-06 16:08:04 -08:00
lambda { | e | e . message == 'Undefined variable: "$bork".' } ,
2010-01-23 17:01:19 -08:00
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
2009-07-11 16:40:23 -04:00
## 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_ " ) ]
2010-01-23 16:06:31 -08:00
touch 'basic' , 'more_'
assert_needs_update " import "
2010-04-10 16:32:14 -07:00
update_all_stylesheets!
2009-07-11 16:40:23 -04:00
assert_renders_correctly ( " import " )
ensure
FileUtils . mv ( template_loc ( " basic " , " more_ " ) , template_loc ( " basic " ) )
end
2006-11-28 20:39:33 +00:00
private
2007-08-28 05:33:57 +00:00
2008-08-09 09:43:15 -07:00
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 " )
2009-04-21 14:12:43 -07:00
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
2008-07-14 11:32:08 -07:00
expected_lines . zip ( actual_lines ) . each_with_index do | pair , line |
2008-08-09 09:43:15 -07:00
message = " template: #{ result_name } \n line: #{ line + 1 } "
2006-12-03 23:17:45 +00:00
assert_equal ( pair . first , pair . last , message )
end
2008-07-27 12:46:57 -07:00
if expected_lines . size < actual_lines . size
2008-08-09 09:43:15 -07:00
assert ( false , " #{ actual_lines . size - expected_lines . size } Trailing lines found in #{ tempfile_name } .css: #{ actual_lines [ expected_lines . size .. - 1 ] . join ( '\n' ) } " )
2008-07-27 12:46:57 -07:00
end
2006-12-03 23:17:45 +00:00
end
2007-08-28 05:33:57 +00:00
2009-12-24 12:06:51 -08:00
def assert_stylesheet_updated ( name )
2010-01-23 16:06:31 -08:00
assert_doesnt_need_update name
2009-12-24 12:06:51 -08:00
# Make sure it isn't an exception
expected_lines = File . read ( result_loc ( name ) ) . split ( " \n " )
actual_lines = File . read ( tempfile_loc ( name ) ) . 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 " ) )
end
end
2010-01-23 15:37:39 -08:00
def assert_callback ( name , * expected_args )
run = false
2010-01-23 17:01:19 -08:00
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
2010-01-23 15:37:39 -08:00
end
if block_given?
yield
else
2010-04-10 16:32:14 -07:00
update_all_stylesheets!
2010-01-23 15:37:39 -08:00
end
assert run , " Expected #{ name } callback to be run with arguments: \n #{ expected_args . inspect } "
end
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
2010-04-10 16:32:14 -07:00
update_all_stylesheets!
2010-01-23 15:37:39 -08:00
end
end
def assert_callbacks ( * args )
2010-04-10 16:32:14 -07:00
return update_all_stylesheets! if args . empty?
2010-01-23 15:37:39 -08:00
assert_callback ( * args . pop ) { assert_callbacks ( * args ) }
end
2010-01-23 16:25:01 -08:00
def assert_no_callbacks ( * args )
2010-04-10 16:32:14 -07:00
return update_all_stylesheets! if args . empty?
2010-01-23 16:25:01 -08:00
assert_no_callback ( * args . pop ) { assert_no_callbacks ( * args ) }
end
2010-01-23 15:37:39 -08:00
def clear_callbacks
Sass :: Plugin . instance_variable_set ( '@_sass_callbacks' , { } )
end
2010-04-10 16:32:14 -07:00
def update_all_stylesheets!
Haml :: Util . silence_haml_warnings do
Sass :: Plugin . update_stylesheets
end
end
2010-05-10 21:37:57 -07:00
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. " )
2010-01-23 16:06:31 -08:00
end
2010-05-10 21:37:57 -07:00
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. " )
2010-01-23 16:06:31 -08:00
end
def touch ( * args )
FileUtils . touch ( template_loc ( * args ) )
end
def reset_mtimes
2010-04-11 21:53:22 +02:00
Sass :: Plugin :: StalenessChecker . dependencies_cache = { }
2010-01-30 15:38:08 -08:00
atime = Time . now
2010-01-30 16:10:49 -08:00
mtime = Time . now - 5
Dir [ " { #{ template_loc } , #{ tempfile_loc } }/**/*.{css,sass,scss} " ] . each { | f | File . utime ( atime , mtime , f ) }
2010-01-23 16:06:31 -08:00
end
2008-07-14 11:32:08 -07:00
def template_loc ( name = nil , prefix = nil )
if name
2009-12-31 17:55:45 -08:00
scss = absolutize " #{ prefix } templates/ #{ name } .scss "
File . exists? ( scss ) ? scss : absolutize ( " #{ prefix } templates/ #{ name } .sass " )
2008-07-14 11:32:08 -07:00
else
absolutize " #{ prefix } templates "
end
2007-09-02 01:48:25 +00:00
end
2008-07-14 11:32:08 -07:00
def tempfile_loc ( name = nil , prefix = nil )
if name
absolutize " #{ prefix } tmp/ #{ name } .css "
else
absolutize " #{ prefix } tmp "
end
end
def result_loc ( name = nil , prefix = nil )
if name
absolutize " #{ prefix } results/ #{ name } .css "
else
absolutize " #{ prefix } results "
end
2006-11-28 20:39:33 +00:00
end
2007-08-28 05:33:57 +00:00
2008-07-14 11:32:08 -07:00
def absolutize ( file )
" #{ File . dirname ( __FILE__ ) } / #{ file } "
2006-12-04 02:47:37 +00:00
end
2007-11-17 19:55:26 +00:00
2008-07-14 11:32:08 -07:00
def set_plugin_opts ( overrides = { } )
2007-11-17 19:55:26 +00:00
Sass :: Plugin . options = {
2008-07-14 11:32:08 -07:00
:template_location = > template_loc ,
:css_location = > tempfile_loc ,
2007-11-17 19:55:26 +00:00
:style = > :compact ,
2008-07-14 11:32:08 -07:00
:load_paths = > [ result_loc ] ,
2007-11-17 19:55:26 +00:00
:always_update = > true ,
2010-01-23 16:25:01 -08:00
:never_update = > false ,
2008-07-14 11:32:08 -07:00
} . merge ( overrides )
2007-11-17 19:55:26 +00:00
end
2006-12-04 02:47:37 +00:00
end
2006-12-22 06:59:38 +00:00
class Sass :: Engine
alias_method :old_render , :render
2007-08-28 05:33:57 +00:00
2006-12-22 06:59:38 +00:00
def render
raise " bork bork bork! " if @template [ 0 ] == " {bork now!} "
old_render
end
end