diff --git a/lib/sass_spec/cli.rb b/lib/sass_spec/cli.rb index ce3d998041..4cb81d9bcb 100644 --- a/lib/sass_spec/cli.rb +++ b/lib/sass_spec/cli.rb @@ -1,10 +1,11 @@ +require_relative 'engine_adapter' module SassSpec::CLI require 'optparse' def self.parse options = { - sass_executable: "sass", + engine_adapter: SassEngineAdapter.new("sass"), spec_directory: "spec", tap: false, skip: false, @@ -47,8 +48,8 @@ def self.parse options[:tap] = true end - opts.on("-c", "--command COMMAND", "Sets a specific binary to run (defaults to '#{options[:sass_executable]}')") do |v| - options[:sass_executable] = v + opts.on("-c", "--command COMMAND", "Sets a specific binary to run (defaults to '#{options[:engine_adapter]}')") do |v| + options[:engine_adapter] = ExecutableEngineAdapater.new(v) end opts.on("--ignore-todo", "Skip any folder named 'todo'") do diff --git a/lib/sass_spec/engine_adapter.rb b/lib/sass_spec/engine_adapter.rb new file mode 100644 index 0000000000..692c832b63 --- /dev/null +++ b/lib/sass_spec/engine_adapter.rb @@ -0,0 +1,83 @@ +require "open3" + +class EngineAdapter + def describe + not_implemented + end + + # The version string of the implementation + def version + not_implemented + end + + def to_s + describe + end + + # Compile a Sass file and return the results + # @return [css_output, std_error, status_code] + def compile(sass_filename) + not_implemented + end + + private + + def not_implemented + raise RuntimeError, "Not yet implemented" + end +end + +class ExecutableEngineAdapater < EngineAdapter + + def initialize(command, description = nil) + @command = command + @description = description || command + end + + def describe + @description + end + + def version + stdout, stderr, status = Open3.capture3("#{@command} -v") + stdout.to_s + end + + + def compile(sass_filename) + Open3.capture3("#{@command} #{sass_filename}") + end +end + +class SassEngineAdapter < EngineAdapter + def initialize(description) + @description = description + end + + def describe + @description + end + + def version + require 'sass/version' + Sass::VERSION + end + + def compile(sass_filename) + require 'sass' + begin + captured_stderr = StringIO.new + real_stderr, $stderr = $stderr, captured_stderr + begin + css_output = Sass.compile_file(sass_filename.to_s) + [css_output, captured_stderr.to_s, 0] + rescue Sass::SyntaxError => e + [Sass::SyntaxError.exception_to_css(e), captured_stderr.string, 1] + rescue => e + [Sass::SyntaxError.exception_to_css(e), captured_stderr.string, 2] + end + ensure + $stderr = real_stderr + end + end +end diff --git a/lib/sass_spec/runner.rb b/lib/sass_spec/runner.rb index 79bcaa47d2..6d2389453c 100644 --- a/lib/sass_spec/runner.rb +++ b/lib/sass_spec/runner.rb @@ -12,9 +12,8 @@ def initialize(options = {}) def run unless @options[:silent] || @options[:tap] - puts "Recursively searching under directory '#{@options[:spec_directory]}' for test files to test '#{@options[:sass_executable]}' with." - stdout, stderr, status = Open3.capture3("#{@options[:sass_executable]} -v") - puts stdout + puts "Recursively searching under directory '#{@options[:spec_directory]}' for test files to test '#{@options[:engine_adapter]}' with." + puts @options[:engine_adapter].version end test_cases = _get_cases diff --git a/lib/sass_spec/test.rb b/lib/sass_spec/test.rb index b203abb813..52a80bc581 100644 --- a/lib/sass_spec/test.rb +++ b/lib/sass_spec/test.rb @@ -11,7 +11,7 @@ def run_spec_test(test_case, options = {}) output, clean_output, error, status = test_case.output if status != 0 && !options[:unexpected_pass] - msg = "Command `#{options[:sass_executable]}` did not complete:\n\n#{error}" + msg = "Command `#{options[:engine_adapter]}` did not complete:\n\n#{error}" if options[:skip] raise msg diff --git a/lib/sass_spec/test_case.rb b/lib/sass_spec/test_case.rb index fa10c546b7..8a77a3861c 100644 --- a/lib/sass_spec/test_case.rb +++ b/lib/sass_spec/test_case.rb @@ -1,4 +1,3 @@ -require "open3" # This represents a specific test case. class SassSpec::TestCase def initialize(input_scss, expected_css, options = {}) @@ -27,7 +26,7 @@ def output if @output return @output end - stdout, stderr, status = Open3.capture3("#{@options[:sass_executable]} #{@input_path}") + stdout, stderr, status = engine.compile(@input_path) cleaned = _clean_output(stdout) @output ||= [stdout, cleaned, stderr, status] end @@ -36,6 +35,10 @@ def expected @expected ||= _clean_output File.read(@expected_path) end + def engine + @options[:engine_adapter] + end + def _clean_output(css) css.gsub(/\s+/, " ") .gsub(/ *\{/, " {\n")