From f3bcbaee198f23f8db13e2170155e4be0c91a17f Mon Sep 17 00:00:00 2001 From: Brandon Mathis Date: Fri, 7 Jan 2011 17:45:30 -0600 Subject: [PATCH 01/15] added redirect for reference and updated general layouts redirect --- doc-src/content/reference.haml | 4 ++++ doc-src/layouts/redirect.haml | 5 +++++ 2 files changed, 9 insertions(+) create mode 100644 doc-src/content/reference.haml create mode 100644 doc-src/layouts/redirect.haml diff --git a/doc-src/content/reference.haml b/doc-src/content/reference.haml new file mode 100644 index 00000000..594a4334 --- /dev/null +++ b/doc-src/content/reference.haml @@ -0,0 +1,4 @@ +--- +title: Compass Documentation +redirect: /reference/compass/ +--- \ No newline at end of file diff --git a/doc-src/layouts/redirect.haml b/doc-src/layouts/redirect.haml new file mode 100644 index 00000000..5c7c76ff --- /dev/null +++ b/doc-src/layouts/redirect.haml @@ -0,0 +1,5 @@ +!!!5 +- # This template redirects. +%html{:dir => "ltr", :lang => "en"} + %head + %meta{:"http-equiv" => "refresh", :content => "0;#{@item[:redirect]}"}/ \ No newline at end of file From 0d029e6a02c3d7cf577df40f6974f4db8c40fdfc Mon Sep 17 00:00:00 2001 From: Scott Davis Date: Sun, 24 Apr 2011 23:23:07 -0400 Subject: [PATCH 02/15] merge --- Gemfile | 6 +++++- Gemfile.lock | 8 ++++++-- doc-src/Gemfile | 1 + doc-src/Gemfile.lock | 6 +++--- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index ead7dac2..b102fdf4 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,6 @@ source :rubygems gemspec -#gem "compass", :path => "." #no idea but it fixed my rage - sdavis gem "cucumber", "~> 0.9.2" gem "rspec", "~>2.0.0" gem "rails", "~>3.0.0.rc" @@ -17,7 +16,12 @@ gem "rb-fsevent" gem "ruby-prof" unless RUBY_PLATFORM == "java" + gem 'autotest' +gem 'autotest-fsevent' gem 'fakefs', :git => 'git://github.com/johnbintz/fakefs.git' gem 'mocha' gem 'timecop' + + + diff --git a/Gemfile.lock b/Gemfile.lock index f329954b..4f3fe2a1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,7 +7,7 @@ GIT PATH remote: . specs: - compass (0.11.beta.7.a997fa2) + compass (0.11.beta.7.5962a85) chunky_png (~> 1.1.1) fssm (>= 0.2.7) sass (>= 3.1.0.alpha.249) @@ -47,6 +47,8 @@ GEM arel (2.0.9) autotest (4.4.6) ZenTest (>= 4.4.1) + autotest-fsevent (0.2.5) + sys-uname builder (2.1.2) chunky_png (1.1.1) compass-validator (3.0.0) @@ -69,7 +71,7 @@ GEM gherkin (2.2.9) json (~> 1.4.6) term-ansicolor (~> 1.0.5) - haml (3.1.0.alpha.147) + haml (3.1.0) i18n (0.5.0) json (1.4.6) livereload (1.6) @@ -119,6 +121,7 @@ GEM ruby-prof (0.10.5) rubyzip (0.9.4) sass (3.1.0.alpha.263) + sys-uname (0.8.5) term-ansicolor (1.0.5) thor (0.14.6) timecop (0.3.5) @@ -131,6 +134,7 @@ PLATFORMS DEPENDENCIES autotest + autotest-fsevent compass! compass-validator (= 3.0.0) css_parser (~> 1.0.1) diff --git a/doc-src/Gemfile b/doc-src/Gemfile index 1b09d7ac..02cd4b7f 100644 --- a/doc-src/Gemfile +++ b/doc-src/Gemfile @@ -19,3 +19,4 @@ gem 'css_parser', "1.0.1" gem 'ruby-prof' gem 'rb-fsevent' + diff --git a/doc-src/Gemfile.lock b/doc-src/Gemfile.lock index 46916319..f489eada 100644 --- a/doc-src/Gemfile.lock +++ b/doc-src/Gemfile.lock @@ -8,8 +8,8 @@ GIT PATH remote: .. specs: - compass (0.11.beta.7.f4ac295) - chunky_png (~> 1.1.0) + compass (0.11.beta.7.5962a85) + chunky_png (~> 1.1.1) fssm (>= 0.2.7) sass (>= 3.1.0.alpha.249) @@ -17,7 +17,7 @@ GEM remote: http://rubygems.org/ specs: activesupport (3.0.5) - chunky_png (1.1.0) + chunky_png (1.1.1) coderay (0.9.7) compass-susy-plugin (0.9.beta.3) compass (>= 0.11.beta.3) From a58a66c4c251ded431a82d907dbfc1342db390e5 Mon Sep 17 00:00:00 2001 From: Scott Davis Date: Mon, 25 Apr 2011 01:44:08 -0400 Subject: [PATCH 03/15] added application integration to turtorials --- doc-src/Gemfile.lock | 2 +- .../help/tutorials/integration.markdown | 83 +++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 doc-src/content/help/tutorials/integration.markdown diff --git a/doc-src/Gemfile.lock b/doc-src/Gemfile.lock index f489eada..4a75775a 100644 --- a/doc-src/Gemfile.lock +++ b/doc-src/Gemfile.lock @@ -8,7 +8,7 @@ GIT PATH remote: .. specs: - compass (0.11.beta.7.5962a85) + compass (0.11.beta.7.e3aa9aa) chunky_png (~> 1.1.1) fssm (>= 0.2.7) sass (>= 3.1.0.alpha.249) diff --git a/doc-src/content/help/tutorials/integration.markdown b/doc-src/content/help/tutorials/integration.markdown new file mode 100644 index 00000000..daac952b --- /dev/null +++ b/doc-src/content/help/tutorials/integration.markdown @@ -0,0 +1,83 @@ +--- +title: Application Integration +layout: tutorial +crumb: Appliction Integration +classnames: + - tutorial +--- +# Application Integration + +## Ruby on Rails + +### Rails 3 + compass init rails /path/to/myrailsproject +### Rails 2.3 + rake rails:template LOCATION=http://compass-style.org/rails/installer + +## Sinatra + + require 'sinatra' + require 'haml' + require 'sass' + require 'compass' + + configure do + Compass.configuration do |config| + config.project_path = File.dirname(__FILE__) + config.sass_dir = 'views' + end + + set :haml, { :format => :html5 } + set :sass, Compass.sass_engine_options + end + + get '/screen.css' do + content_type 'text/css', :charset => 'utf-8' + sass :screen + end + +If you keep your stylesheets in “views/stylesheets/” directory instead of just “views/”, remember to update sass_dir configuration accordingly. +Check out this [sample compass-sinatra project](http://github.com/chriseppstein/compass-sinatra) to get up and running in no time! + +[Sinatra Bootstrap](http://github.com/adamstac/sinatra-bootstrap) - a base Sinatra project with support for Haml, Sass, Compass, jQuery and more. + +## Nanoc3 + +### Minimal integration: just drop it in + +One simple route for lightweight integration is to simply install compass inside nanoc. Then edit config.rb to point to the stylesheets you want to use. This means you have to have the Compass watch command running in a separate window from the Nanoc compilation process. + +Example project that works this way: http://github.com/unthinkingly/unthinkingly-blog + +### More formal integration + +At the top of the Nanoc Rules file, load the Compass configuration, like this: + + require 'compass' + + Compass.add_project_configuration 'compass/config.rb' # when using Compass 0.10 + Compass.configuration.parse 'compass/config.rb' # when using Compass < 0.10 + +Your Compass configuration file (in compass/config.rb) could look like this (you may need to change the path to some directories depending on your directory structure): + + http_path = "/" + project_path = "." + css_dir = "output/assets/style" + sass_dir = "content/assets/style" + images_dir = "output/assets/images" + + # when using SCSS: + sass_options = { + :syntax => :scss + } + + +To filter the stylesheets using Sass and Compass, call the sass filter with Sass engine options taken from Compass, like this: + + filter :sass, Compass.sass_engine_options + + +### Nanoc Projects using the formal approach + +* [nanoc Bootstrap](http://github.com/adamstac/nanoc-bootstrap) - a base nanoc project with support for Haml, Sass, Compass, jQuery and more. +* [nanoc & Compass Example Project](http://github.com/ddfreyne/nanoc-bootstrap-compass) \ No newline at end of file From 26f44fd8a20d3aa048d90190a7694507a18bee30 Mon Sep 17 00:00:00 2001 From: Brandon Mathis Date: Tue, 26 Apr 2011 18:34:51 -0500 Subject: [PATCH 04/15] fixed merge --- doc-src/layouts/article.haml | 2 +- doc-src/layouts/example.haml | 2 +- doc-src/lib/search.rb | 58 ++++++++++++++++++------------------ 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/doc-src/layouts/article.haml b/doc-src/layouts/article.haml index 89da0430..6e749f09 100644 --- a/doc-src/layouts/article.haml +++ b/doc-src/layouts/article.haml @@ -12,7 +12,7 @@ Version: %a.number(href="/CHANGELOG/")= compass_version %article= yield - -#comments= render "partials/disqus_comments" + -comments= render "partials/disqus_comments" %footer(role="contentinfo")= render "partials/footer" = @item[:content_for_javascripts] = render "partials/analytics" diff --git a/doc-src/layouts/example.haml b/doc-src/layouts/example.haml index b6e3caf4..67937596 100644 --- a/doc-src/layouts/example.haml +++ b/doc-src/layouts/example.haml @@ -14,7 +14,7 @@ Version: %a.number(href="/CHANGELOG/")= compass_version %article= yield - -#comments= render "partials/disqus_comments" + -comments= render "partials/disqus_comments" %footer(role="contentinfo")= render "partials/footer" = @item[:content_for_javascripts] = render "partials/analytics" diff --git a/doc-src/lib/search.rb b/doc-src/lib/search.rb index f5f5d47b..9ed0de70 100644 --- a/doc-src/lib/search.rb +++ b/doc-src/lib/search.rb @@ -1,35 +1,35 @@ require 'json' STOP_WORDS = %w{ - a about above across after afterwards again against all almost - alone along already also although always am among amongst amoungst - amount an and another any anyhow anyone anything anyway anywhere - are around as at back be became because become becomes becoming - been before beforehand behind being below beside besides between - beyond bill both bottom but by call can cannot cant co computer con - could couldnt cry de describe detail do done down due during each - eg eight either eleven else elsewhere empty enough etc even ever - every everyone everything everywhere except few fifteen fify fill - find fire first five for former formerly forty found four from - front full further get give go had has hasnt have he hence her here - hereafter hereby herein hereupon hers herself him himself his how - however hundred i ie if in inc indeed interest into is it its - itself keep last latter latterly least less ltd made many may me - meanwhile might mill mine more moreover most mostly move much must - my myself name namely neither never nevertheless next nine no - nobody none noone nor not nothing now nowhere of off often on once - one only onto or other others otherwise our ours ourselves out over - own part per perhaps please put rather re same see seem seemed - seeming seems serious several she should show side since sincere - six sixty so some somehow someone something sometime sometimes - somewhere still such system take ten than that the their them - themselves then thence there thereafter thereby therefore therein - thereupon these they thick thin third this those though three - through throughout thru thus to together too top toward towards - twelve twenty two un under until up upon us very via was we well - were what whatever when whence whenever where whereafter whereas - whereby wherein whereupon wherever whether which while whither who - whoever whole whom whose why will with within without would yet you + a about above across after afterwards again against all almost + alone along already also although always am among amongst amoungst + amount an and another any anyhow anyone anything anyway anywhere + are around as at back be became because become becomes becoming + been before beforehand behind being below beside besides between + beyond bill both bottom but by call can cannot cant co computer con + could couldnt cry de describe detail do done down due during each + eg eight either eleven else elsewhere empty enough etc even ever + every everyone everything everywhere except few fifteen fify fill + find fire first five for former formerly forty found four from + front full further get give go had has hasnt have he hence her here + hereafter hereby herein hereupon hers herself him himself his how + however hundred i ie if in inc indeed interest into is it its + itself keep last latter latterly least less ltd made many may me + meanwhile might mill mine more moreover most mostly move much must + my myself name namely neither never nevertheless next nine no + nobody none noone nor not nothing now nowhere of off often on once + one only onto or other others otherwise our ours ourselves out over + own part per perhaps please put rather re same see seem seemed + seeming seems serious several she should show side since sincere + six sixty so some somehow someone something sometime sometimes + somewhere still such system take ten than that the their them + themselves then thence there thereafter thereby therefore therein + thereupon these they thick thin third this those though three + through throughout thru thus to together too top toward towards + twelve twenty two un under until up upon us very via was we well + were what whatever when whence whenever where whereafter whereas + whereby wherein whereupon wherever whether which while whither who + whoever whole whom whose why will with within without would yet you your yours yourself yourselves } unless defined?(STOP_WORDS) From 5cdd9c6d09130e61df19af2aacb391440e851f40 Mon Sep 17 00:00:00 2001 From: Scott Davis Date: Tue, 26 Apr 2011 21:52:47 -0400 Subject: [PATCH 05/15] updated gemfile --- Gemfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index b102fdf4..e37b4129 100644 --- a/Gemfile +++ b/Gemfile @@ -7,8 +7,7 @@ gem "rspec", "~>2.0.0" gem "rails", "~>3.0.0.rc" gem "compass-validator", "3.0.0" gem "css_parser", "~> 1.0.1" -gem "sass", "3.1.0.alpha.263" -gem "haml", "~> 3.1.0.alpha" +#gem "sass", "~> 3.1.1" gem "rcov" gem "rubyzip" gem "livereload" From e78ddf5d72caa9f4f0bf522125050660151f233e Mon Sep 17 00:00:00 2001 From: Scott Davis Date: Tue, 26 Apr 2011 21:59:20 -0400 Subject: [PATCH 06/15] updated gemfile --- Gemfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index e37b4129..d419b455 100644 --- a/Gemfile +++ b/Gemfile @@ -11,13 +11,13 @@ gem "css_parser", "~> 1.0.1" gem "rcov" gem "rubyzip" gem "livereload" -gem "rb-fsevent" +gem "rb-fsevent" if RUBY_PLATFORM ~= /darwin/ gem "ruby-prof" unless RUBY_PLATFORM == "java" gem 'autotest' -gem 'autotest-fsevent' +gem 'autotest-fsevent' if RUBY_PLATFORM ~= /darwin/ gem 'fakefs', :git => 'git://github.com/johnbintz/fakefs.git' gem 'mocha' gem 'timecop' From f1061c474b59b5dafdbe402196071c31e32bef04 Mon Sep 17 00:00:00 2001 From: Scott Davis Date: Tue, 26 Apr 2011 22:00:46 -0400 Subject: [PATCH 07/15] updated gemfile --- Gemfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index d419b455..23e3b6d6 100644 --- a/Gemfile +++ b/Gemfile @@ -11,13 +11,13 @@ gem "css_parser", "~> 1.0.1" gem "rcov" gem "rubyzip" gem "livereload" -gem "rb-fsevent" if RUBY_PLATFORM ~= /darwin/ +gem "rb-fsevent" if RUBY_PLATFORM =~ /darwin/ gem "ruby-prof" unless RUBY_PLATFORM == "java" gem 'autotest' -gem 'autotest-fsevent' if RUBY_PLATFORM ~= /darwin/ +gem 'autotest-fsevent' if RUBY_PLATFORM =~ /darwin/ gem 'fakefs', :git => 'git://github.com/johnbintz/fakefs.git' gem 'mocha' gem 'timecop' From f86bbfc013b0032eb2badcbd2ace10b4397bbd2a Mon Sep 17 00:00:00 2001 From: Brandon Mathis Date: Tue, 26 Apr 2011 22:58:26 -0500 Subject: [PATCH 08/15] updated the sencha site graphic --- .gitignore | 2 ++ Gemfile | 8 ++------ Gemfile.lock | 12 ++++++------ doc-src/.gitignore | 1 + doc-src/Gemfile | 4 ++-- doc-src/Gemfile.lock | 6 +++--- doc-src/assets/images/sites/sencha.jpg | Bin 19890 -> 12925 bytes 7 files changed, 16 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index ecc3e275..6a991e7e 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,5 @@ attic devbin .rvmrc *.rbc +vendor/ruby +vendor diff --git a/Gemfile b/Gemfile index b102fdf4..ae7d4a57 100644 --- a/Gemfile +++ b/Gemfile @@ -7,8 +7,8 @@ gem "rspec", "~>2.0.0" gem "rails", "~>3.0.0.rc" gem "compass-validator", "3.0.0" gem "css_parser", "~> 1.0.1" -gem "sass", "3.1.0.alpha.263" -gem "haml", "~> 3.1.0.alpha" +gem "sass", "3.1" +gem "haml", "~> 3.1" gem "rcov" gem "rubyzip" gem "livereload" @@ -16,12 +16,8 @@ gem "rb-fsevent" gem "ruby-prof" unless RUBY_PLATFORM == "java" - gem 'autotest' gem 'autotest-fsevent' gem 'fakefs', :git => 'git://github.com/johnbintz/fakefs.git' gem 'mocha' gem 'timecop' - - - diff --git a/Gemfile.lock b/Gemfile.lock index ec2d4004..20e317ed 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,10 +7,10 @@ GIT PATH remote: . specs: - compass (0.11.1) - chunky_png (~> 1.1.1) + compass (0.11.1.26f44fd) + chunky_png (~> 1.1) fssm (>= 0.2.7) - sass (>= 3.1.0.alpha.249) + sass (~> 3.1) GEM remote: http://rubygems.org/ @@ -120,7 +120,7 @@ GEM ruby-json (1.1.2) ruby-prof (0.10.5) rubyzip (0.9.4) - sass (3.1.0.alpha.263) + sass (3.1.0) sys-uname (0.8.5) term-ansicolor (1.0.5) thor (0.14.6) @@ -140,7 +140,7 @@ DEPENDENCIES css_parser (~> 1.0.1) cucumber (~> 0.9.2) fakefs! - haml (~> 3.1.0.alpha) + haml (~> 3.1) livereload mocha rails (~> 3.0.0.rc) @@ -149,5 +149,5 @@ DEPENDENCIES rspec (~> 2.0.0) ruby-prof rubyzip - sass (= 3.1.0.alpha.263) + sass (= 3.1) timecop diff --git a/doc-src/.gitignore b/doc-src/.gitignore index 2a378b3c..d9154566 100644 --- a/doc-src/.gitignore +++ b/doc-src/.gitignore @@ -1,3 +1,4 @@ bin vendor output +vendor/ruby diff --git a/doc-src/Gemfile b/doc-src/Gemfile index 02cd4b7f..5b880cc3 100644 --- a/doc-src/Gemfile +++ b/doc-src/Gemfile @@ -8,8 +8,8 @@ gem 'mime-types' gem 'serve', "1.0.0" gem 'nokogiri' gem 'coderay' -gem 'sass', ">= 3.1.0.alpha.249" -gem 'haml', ">= 3.1.0.alpha.36" +gem 'sass', ">= 3.1" +gem 'haml', ">= 3.1" gem 'rake' gem 'compass', :path => ".." gem 'compass-susy-plugin', ">=0.7.0.pre8" diff --git a/doc-src/Gemfile.lock b/doc-src/Gemfile.lock index 669c3b15..14cfbefa 100644 --- a/doc-src/Gemfile.lock +++ b/doc-src/Gemfile.lock @@ -8,7 +8,7 @@ GIT PATH remote: .. specs: - compass (0.11.1.63cae60) + compass (0.11.1.26f44fd) chunky_png (~> 1.1) fssm (>= 0.2.7) sass (~> 3.1) @@ -54,7 +54,7 @@ DEPENDENCIES compass-susy-plugin (>= 0.7.0.pre8) css-slideshow (= 0.2.0) css_parser (= 1.0.1) - haml (>= 3.1.0.alpha.36) + haml (>= 3.1) json mime-types nanoc3! @@ -64,6 +64,6 @@ DEPENDENCIES rb-fsevent rdiscount ruby-prof - sass (>= 3.1.0.alpha.249) + sass (>= 3.1) serve (= 1.0.0) thor diff --git a/doc-src/assets/images/sites/sencha.jpg b/doc-src/assets/images/sites/sencha.jpg index ae31aeda53d3caccd603012ccf0c39b1d7fe3167..4defec706772df4092d0050e7dba89d618d69d57 100644 GIT binary patch literal 12925 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 I&pVI**-wzl*8l(j From c317ef687074af173ecaa6bcb95913397613f6d5 Mon Sep 17 00:00:00 2001 From: Scott Davis Date: Wed, 27 Apr 2011 23:18:52 -0400 Subject: [PATCH 09/15] refactored tests --- Gemfile | 2 + Gemfile.lock | 12 ++--- test/compass_test.rb | 16 +++--- test/configuration_test.rb | 54 +++++++++++++++---- test/fixtures/stylesheets/relative/config.rb | 1 + .../command_line.rb} | 0 test/{io_helper.rb => helpers/io.rb} | 0 test/{rails_helper.rb => helpers/rails.rb} | 1 + test/helpers/test_case.rb | 44 +++++++++++++++ test/rails_integration_test.rb | 1 - test/test_case_helper.rb | 13 ----- test/test_helper.rb | 17 ++++-- 12 files changed, 118 insertions(+), 43 deletions(-) rename test/{command_line_helper.rb => helpers/command_line.rb} (100%) rename test/{io_helper.rb => helpers/io.rb} (100%) rename test/{rails_helper.rb => helpers/rails.rb} (98%) create mode 100644 test/helpers/test_case.rb delete mode 100644 test/test_case_helper.rb diff --git a/Gemfile b/Gemfile index 23e3b6d6..920ce595 100644 --- a/Gemfile +++ b/Gemfile @@ -21,6 +21,8 @@ gem 'autotest-fsevent' if RUBY_PLATFORM =~ /darwin/ gem 'fakefs', :git => 'git://github.com/johnbintz/fakefs.git' gem 'mocha' gem 'timecop' +gem 'diff-lcs', '~> 1.1.2' + diff --git a/Gemfile.lock b/Gemfile.lock index ec2d4004..94766d49 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,10 +7,10 @@ GIT PATH remote: . specs: - compass (0.11.1) - chunky_png (~> 1.1.1) + compass (0.11.1.f1061c4) + chunky_png (~> 1.1) fssm (>= 0.2.7) - sass (>= 3.1.0.alpha.249) + sass (~> 3.1) GEM remote: http://rubygems.org/ @@ -71,7 +71,6 @@ GEM gherkin (2.2.9) json (~> 1.4.6) term-ansicolor (~> 1.0.5) - haml (3.1.0) i18n (0.5.0) json (1.4.6) livereload (1.6) @@ -120,7 +119,7 @@ GEM ruby-json (1.1.2) ruby-prof (0.10.5) rubyzip (0.9.4) - sass (3.1.0.alpha.263) + sass (3.1.1) sys-uname (0.8.5) term-ansicolor (1.0.5) thor (0.14.6) @@ -139,8 +138,8 @@ DEPENDENCIES compass-validator (= 3.0.0) css_parser (~> 1.0.1) cucumber (~> 0.9.2) + diff-lcs (~> 1.1.2) fakefs! - haml (~> 3.1.0.alpha) livereload mocha rails (~> 3.0.0.rc) @@ -149,5 +148,4 @@ DEPENDENCIES rspec (~> 2.0.0) ruby-prof rubyzip - sass (= 3.1.0.alpha.263) timecop diff --git a/test/compass_test.rb b/test/compass_test.rb index 02920954..26491328 100644 --- a/test/compass_test.rb +++ b/test/compass_test.rb @@ -5,18 +5,14 @@ require 'compass/logger' require 'sass/plugin' class CompassTest < Test::Unit::TestCase - include Compass::TestCaseHelper + def setup Compass.reset_configuration! end def teardown - teardown_fixtures :blueprint, :empty, :compass, :image_urls, :relative - end - - def teardown_fixtures(*project_names) - project_names.each do |project_name| - FileUtils.rm_rf tempfile_path(project_name) + [:blueprint, :empty, :compass, :image_urls, :relative].each do |project_name| + ::FileUtils.rm_rf tempfile_path(project_name) end end @@ -117,7 +113,11 @@ private expected_lines = expected_lines.split("\n").reject{|l| l=~/\A\Z/} expected_lines.zip(actual_lines).each_with_index do |pair, line| message = "template: #{name}\nline: #{line + 1}" - assert_equal(pair.first, pair.last, message) + if pair.first == pair.last + assert(true) + else + assert false, diff_as_string(pair.first.inspect, pair.last.inspect) + end end if expected_lines.size < actual_lines.size assert(false, "#{actual_lines.size - expected_lines.size} Trailing lines found in #{actual_result_file}.css: #{actual_lines[expected_lines.size..-1].join('\n')}") diff --git a/test/configuration_test.rb b/test/configuration_test.rb index 419e5b27..3e97a722 100644 --- a/test/configuration_test.rb +++ b/test/configuration_test.rb @@ -3,9 +3,12 @@ require 'compass' require 'stringio' class ConfigurationTest < Test::Unit::TestCase - include Compass::IoHelper - def setup + setup do + Compass.reset_configuration! + end + + after do Compass.reset_configuration! end @@ -15,18 +18,23 @@ class ConfigurationTest < Test::Unit::TestCase # Require any additional compass plugins here. project_type = :stand_alone + # Set this to the root of your project when deployed: http_path = "/" css_dir = "css" sass_dir = "sass" images_dir = "img" javascripts_dir = "js" + output_style = :nested + # To enable relative paths to assets via compass helper functions. Uncomment: # relative_assets = true + # To disable debugging comments that display the original location of your selectors. Uncomment: # line_comments = false + # If you prefer the indented syntax, you might want to regenerate this # project again passing --syntax sass, or you can uncomment this: # preferred_syntax = :sass @@ -43,7 +51,7 @@ class ConfigurationTest < Test::Unit::TestCase expected_lines = contents.string.split("\n").map{|l|l.strip} actual_lines = Compass.configuration.serialize.split("\n").map{|l|l.strip} - assert_equal expected_lines, actual_lines + assert_correct expected_lines, actual_lines end def test_serialization_warns_with_asset_host_set @@ -101,19 +109,23 @@ class ConfigurationTest < Test::Unit::TestCase expected_serialization = <"bar"} +# relative_assets = true\nsass_options = {:foo=>\"bar\"} + # To disable debugging comments that display the original location of your selectors. Uncomment: # line_comments = false + EXPECTED - assert_equal expected_serialization, Compass.configuration.serialize + assert_correct(expected_serialization, Compass.configuration.serialize) end def test_strip_trailing_directory_separators @@ -223,18 +243,24 @@ EXPECTED assert_equal "baz", Compass.configuration.foobar expected_serialization = < Date: Wed, 27 Apr 2011 23:19:41 -0400 Subject: [PATCH 10/15] diff helper --- test/helpers/diff.rb | 49 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 test/helpers/diff.rb diff --git a/test/helpers/diff.rb b/test/helpers/diff.rb new file mode 100644 index 00000000..e7a4e24d --- /dev/null +++ b/test/helpers/diff.rb @@ -0,0 +1,49 @@ +require 'diff/lcs' +require 'diff/lcs/hunk' +module Compass + module Diff + #stole this from rspec who stole this from the gem + def diff_as_string(data_new, data_old) + data_old = data_old.split(/\n/).map! { |e| e.chomp } + data_new = data_new.split(/\n/).map! { |e| e.chomp } + output = "" + diffs = ::Diff::LCS.diff(data_old, data_new) + return output if diffs.empty? + oldhunk = hunk = nil + file_length_difference = 0 + diffs.each do |piece| + begin + hunk = ::Diff::LCS::Hunk.new( + data_old, data_new, piece, context_lines, file_length_difference + ) + file_length_difference = hunk.file_length_difference + next unless oldhunk + # Hunks may overlap, which is why we need to be careful when our + # diff includes lines of context. Otherwise, we might print + # redundant lines. + if (context_lines > 0) and hunk.overlaps?(oldhunk) + hunk.unshift(oldhunk) + else + output << oldhunk.diff(format) + end + ensure + oldhunk = hunk + output << "\n" + end + end + #Handle the last remaining hunk + output << oldhunk.diff(format) << "\n" + end + + protected + + def format + :unified + end + + def context_lines + 3 + end + + end +end \ No newline at end of file From f4f9d7bfdc36a95aabaa027f8282ee5d7a5fcfe2 Mon Sep 17 00:00:00 2001 From: Scott Davis Date: Wed, 27 Apr 2011 23:23:14 -0400 Subject: [PATCH 11/15] fixed merge in gemfile --- Gemfile | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Gemfile b/Gemfile index 8684c90a..8ad85545 100644 --- a/Gemfile +++ b/Gemfile @@ -21,11 +21,5 @@ gem 'autotest-fsevent' if RUBY_PLATFORM =~ /darwin/ gem 'fakefs', :git => 'git://github.com/johnbintz/fakefs.git' gem 'mocha' gem 'timecop' -<<<<<<< HEAD gem 'diff-lcs', '~> 1.1.2' - - - -======= ->>>>>>> f3ea546150ded6fb0ee1ca91cde4c0349f088ddd From 3356303eb367993beb83f7d597fdd9b6310df1ba Mon Sep 17 00:00:00 2001 From: Scott Davis Date: Thu, 28 Apr 2011 00:00:54 -0400 Subject: [PATCH 12/15] sprite tests moved over --- Gemfile.lock | 13 +- test/configuration_test.rb | 9 - .../public/images/ko/default_background.png | Bin 0 -> 3113 bytes .../sprites/public/images/ko/starbg26x27.png | Bin 0 -> 1079 bytes .../images/nested/squares/ten-by-ten.png | Bin 0 -> 2804 bytes .../sprites/public/images/prefix/20-by-20.png | Bin 0 -> 2799 bytes .../public/images/prefix/ten-by-ten.png | Bin 0 -> 2804 bytes .../public/images/selectors/ten-by-ten.png | Bin 0 -> 2804 bytes .../images/selectors/ten-by-ten_active.png | Bin 0 -> 2804 bytes .../images/selectors/ten-by-ten_hover.png | Bin 0 -> 2804 bytes .../images/selectors/ten-by-ten_target.png | Bin 0 -> 2804 bytes .../public/images/squares/ten-by-ten.png | Bin 0 -> 2804 bytes .../images/squares/twenty-by-twenty.png | Bin 0 -> 2799 bytes test/helpers/test_case.rb | 9 + test/sprites_test.rb | 550 ++++++++++++++++++ 15 files changed, 561 insertions(+), 20 deletions(-) create mode 100644 test/fixtures/sprites/public/images/ko/default_background.png create mode 100755 test/fixtures/sprites/public/images/ko/starbg26x27.png create mode 100644 test/fixtures/sprites/public/images/nested/squares/ten-by-ten.png create mode 100644 test/fixtures/sprites/public/images/prefix/20-by-20.png create mode 100644 test/fixtures/sprites/public/images/prefix/ten-by-ten.png create mode 100644 test/fixtures/sprites/public/images/selectors/ten-by-ten.png create mode 100644 test/fixtures/sprites/public/images/selectors/ten-by-ten_active.png create mode 100644 test/fixtures/sprites/public/images/selectors/ten-by-ten_hover.png create mode 100644 test/fixtures/sprites/public/images/selectors/ten-by-ten_target.png create mode 100644 test/fixtures/sprites/public/images/squares/ten-by-ten.png create mode 100644 test/fixtures/sprites/public/images/squares/twenty-by-twenty.png create mode 100644 test/sprites_test.rb diff --git a/Gemfile.lock b/Gemfile.lock index 29487042..fd728c5c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,7 +7,7 @@ GIT PATH remote: . specs: - compass (0.11.1.f1061c4) + compass (0.11.1.f4f9d7b) chunky_png (~> 1.1) fssm (>= 0.2.7) sass (~> 3.1) @@ -71,6 +71,7 @@ GEM gherkin (2.2.9) json (~> 1.4.6) term-ansicolor (~> 1.0.5) + haml (3.1.1) i18n (0.5.0) json (1.4.6) livereload (1.6) @@ -119,11 +120,7 @@ GEM ruby-json (1.1.2) ruby-prof (0.10.5) rubyzip (0.9.4) -<<<<<<< HEAD - sass (3.1.1) -======= sass (3.1.0) ->>>>>>> f3ea546150ded6fb0ee1ca91cde4c0349f088ddd sys-uname (0.8.5) term-ansicolor (1.0.5) thor (0.14.6) @@ -144,10 +141,7 @@ DEPENDENCIES cucumber (~> 0.9.2) diff-lcs (~> 1.1.2) fakefs! -<<<<<<< HEAD -======= haml (~> 3.1) ->>>>>>> f3ea546150ded6fb0ee1ca91cde4c0349f088ddd livereload mocha rails (~> 3.0.0.rc) @@ -156,8 +150,5 @@ DEPENDENCIES rspec (~> 2.0.0) ruby-prof rubyzip -<<<<<<< HEAD -======= sass (= 3.1) ->>>>>>> f3ea546150ded6fb0ee1ca91cde4c0349f088ddd timecop diff --git a/test/configuration_test.rb b/test/configuration_test.rb index 3e97a722..792df86d 100644 --- a/test/configuration_test.rb +++ b/test/configuration_test.rb @@ -281,13 +281,4 @@ EXPECTED end.compact end - def assert_correct(before, after) - if before == after - assert(true) - else - assert false, diff_as_string(before.inspect, after.inspect) - end - end - - end diff --git a/test/fixtures/sprites/public/images/ko/default_background.png b/test/fixtures/sprites/public/images/ko/default_background.png new file mode 100644 index 0000000000000000000000000000000000000000..b98cd7f9476b78880c84f878790179263f802257 GIT binary patch literal 3113 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 DNFA4( literal 0 HcmV?d00001 diff --git a/test/fixtures/sprites/public/images/ko/starbg26x27.png b/test/fixtures/sprites/public/images/ko/starbg26x27.png new file mode 100755 index 0000000000000000000000000000000000000000..48dee0dba6a00fd37685ac90a39858d86aa50cdd GIT binary patch literal 1079 zcmV-71jze|P)mBv)T{f%L8uR=8ohvIVB^HY% zp-(-<7P+Yd``vE$@cH?9wQxC|&VIe?DYlST2afIU?}sH4Ld@s$A%cwsmt9}D4CQ({ z1d->iQoWeSWHN~Kh(=Kp2n0Iyex#s^J{(DSstB3PsE26lIM zNA%5rXccwTNGnVb1%-maV0>?HZ$X?YinyX$sG|8+z_wCtg(^WwhOYgKbo)F2>y!fOt9 z8LLY5w8i6bHs2NZM6ZFtrTeJYb0eJ8GbSo?#cFlEOzrIKl<7by5e{KJI5@CwY;0I` zD_}JnTLp~(-3D5nY!GLNpNJP?JXZ)`=OpG1g+g|Z$78RotR#A1kZ%d*t0fO)hg}GF z2}BVb7BtI+#X$>#qT)X{1;fe{Yki_Y1aqj@-yzW`7k!3_KZ~g79Q-CKA}31T*9ipZBK}Ko3+e>?=6y^&6MX{v z2<(CYO4vftMg{)jHFZEND?(-*O1D)Atj*d>$5C*XpzZU{5QWCiNf92`jL_8T`w2h|DN5mXSG)LDLX9w*nc`KzXzHTbUtaz(^k< z{N*=S3U)j+&_QH}5E&r`*!f>V6mQxbMwiTp*Ma~jC|S4!GeJkvVblmgAS0~1bk*qH zg@xxF@LoI>Sj6n)Zp0?C!{TgHAOeem?25J!=l){qvol1aAVgCXb#XBEQcG$^GZj6f xY{bkNVqw8(ycJxwMPIabhY{m8;nuiv{Q`evSC2M2B`^R0002ovPDHLkV1mf%+(rNZ literal 0 HcmV?d00001 diff --git a/test/fixtures/sprites/public/images/nested/squares/ten-by-ten.png b/test/fixtures/sprites/public/images/nested/squares/ten-by-ten.png new file mode 100644 index 0000000000000000000000000000000000000000..c0ae53ccadde24b58be417ca95dcb57eb6da4f1a GIT binary patch literal 2804 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 BIe!2E literal 0 HcmV?d00001 diff --git a/test/fixtures/sprites/public/images/prefix/ten-by-ten.png b/test/fixtures/sprites/public/images/prefix/ten-by-ten.png new file mode 100644 index 0000000000000000000000000000000000000000..c0ae53ccadde24b58be417ca95dcb57eb6da4f1a GIT binary patch literal 2804 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 BIe!2E literal 0 HcmV?d00001 diff --git a/test/helpers/test_case.rb b/test/helpers/test_case.rb index a4a6645f..530ba59e 100644 --- a/test/helpers/test_case.rb +++ b/test/helpers/test_case.rb @@ -9,6 +9,15 @@ module Compass File.join(File.expand_path('../../', __FILE__), path) end end + + def assert_correct(before, after) + if before == after + assert(true) + else + assert false, diff_as_string(before.inspect, after.inspect) + end + end + module ClassMethods def it(name, &block) diff --git a/test/sprites_test.rb b/test/sprites_test.rb new file mode 100644 index 00000000..8e6f4173 --- /dev/null +++ b/test/sprites_test.rb @@ -0,0 +1,550 @@ +require 'test_helper' +require 'fileutils' +require 'compass' +require 'compass/logger' +require 'sass/plugin' + + +class SpritesTest < Test::Unit::TestCase + + def setup + Compass.reset_configuration! + @images_src_path = File.join(File.dirname(__FILE__), 'fixtures', 'sprites', 'public', 'images') + @images_tmp_path = File.join(File.dirname(__FILE__), 'fixtures', 'sprites', 'public', 'images-tmp') + ::FileUtils.cp_r @images_src_path, @images_tmp_path + file = StringIO.new("images_path = #{@images_tmp_path.inspect}\n") + Compass.add_configuration(file, "sprite_config") + Compass.configure_sass_plugin! + end + + def teardown + Compass.reset_configuration! + ::FileUtils.rm_r @images_tmp_path + end + + + def map_location(file) + Dir.glob(File.join(@images_tmp_path, file)).first + end + + def image_size(file) + IO.read(map_location(file))[0x10..0x18].unpack('NN') + end + + def image_md5(file) + md5 = Digest::MD5.new + md5.update IO.read(map_location(file)) + md5.hexdigest + end + + def render(scss) + scss = %Q(@import "compass"; #{scss}) + options = Compass.sass_engine_options + options[:line_comments] = false + options[:style] = :expanded + options[:syntax] = :scss + css = Sass::Engine.new(scss, options).render + # reformat to fit result of heredoc: + " #{css.gsub('@charset "UTF-8";', '').gsub(/\n/, "\n ").strip}\n" + end + + it "should generate sprite classes" do + css = render <<-SCSS + @import "squares/*.png"; + @include all-squares-sprites; + SCSS + assert_correct css, <<-CSS + .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { + background: url('/squares-161c60ad78.png') no-repeat; + } + + .squares-ten-by-ten { + background-position: 0 0; + } + + .squares-twenty-by-twenty { + background-position: 0 -10px; + } + CSS + assert_equal image_size('squares-*.png'), [20, 30] + assert_equal image_md5('squares-*.png'), 'fcc93d7b279c2ad6898fbca49cbd01e1' + end + + it "should generate sprite classes with dimensions" do + css = render <<-SCSS + $squares-sprite-dimensions: true; + @import "squares/*.png"; + @include all-squares-sprites; + SCSS + assert_correct css, <<-CSS + .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { + background: url('/squares-161c60ad78.png') no-repeat; + } + + .squares-ten-by-ten { + background-position: 0 0; + height: 10px; + width: 10px; + } + + .squares-twenty-by-twenty { + background-position: 0 -10px; + height: 20px; + width: 20px; + } + CSS + assert_equal image_size('squares-*.png'), [20, 30] + end + + it "should provide sprite mixin" do + css = render <<-SCSS + @import "squares/*.png"; + + .cubicle { + @include squares-sprite("ten-by-ten"); + } + + .large-cube { + @include squares-sprite("twenty-by-twenty", true); + } + SCSS + assert_correct css, <<-CSS + .squares-sprite, .cubicle, .large-cube { + background: url('/squares-161c60ad78.png') no-repeat; + } + + .cubicle { + background-position: 0 0; + } + + .large-cube { + background-position: 0 -10px; + height: 20px; + width: 20px; + } + CSS + assert_equal image_size('squares-*.png'), [20, 30] + end + + # CUSTOMIZATIONS: + + it "should be possible to change the base class" do + css = render <<-SCSS + $squares-sprite-base-class: ".circles"; + @import "squares/*.png"; + SCSS + assert_correct css, <<-CSS + .circles { + background: url('/squares-161c60ad78.png') no-repeat; + } + CSS + assert_equal image_size('squares-*.png'), [20, 30] + end + + it "should calculate the spacing between images but not before first image" do + css = render <<-SCSS + $squares-ten-by-ten-spacing: 33px; + @import "squares/*.png"; + @include all-squares-sprites; + SCSS + assert_correct css, <<-CSS + .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { + background: url('/squares-89450808af.png') no-repeat; + } + + .squares-ten-by-ten { + background-position: 0 0; + } + + .squares-twenty-by-twenty { + background-position: 0 -43px; + } + CSS + assert_equal image_size('squares-*.png'), [20, 63] + end + + it "should calculate the spacing between images" do + css = render <<-SCSS + $squares-twenty-by-twenty-spacing: 33px; + @import "squares/*.png"; + @include all-squares-sprites; + SCSS + assert_correct css, <<-CSS + .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { + background: url('/squares-673837183a.png') no-repeat; + } + + .squares-ten-by-ten { + background-position: 0 0; + } + + .squares-twenty-by-twenty { + background-position: 0 -43px; + } + CSS + assert_equal image_size('squares-*.png'), [20, 63] + end + + it "should calculate the maximum spacing between images" do + css = render <<-SCSS + $squares-ten-by-ten-spacing: 44px; + $squares-twenty-by-twenty-spacing: 33px; + @import "squares/*.png"; + @include all-squares-sprites; + SCSS + assert_correct css, <<-CSS + .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { + background: url('/squares-1cd84c9068.png') no-repeat; + } + + .squares-ten-by-ten { + background-position: 0 0; + } + + .squares-twenty-by-twenty { + background-position: 0 -54px; + } + CSS + assert_equal image_size('squares-*.png'), [20, 74] + end + + it "should calculate the maximum spacing between images in reversed order" do + css = render <<-SCSS + $squares-ten-by-ten-spacing: 33px; + $squares-twenty-by-twenty-spacing: 44px; + @import "squares/*.png"; + @include all-squares-sprites; + SCSS + assert_correct css, <<-CSS + .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { + background: url('/squares-f25b7090ca.png') no-repeat; + } + + .squares-ten-by-ten { + background-position: 0 0; + } + + .squares-twenty-by-twenty { + background-position: 0 -54px; + } + CSS + assert_equal image_size('squares-*.png'), [20, 74] + end + + it "should calculate the default spacing between images" do + css = render <<-SCSS + $squares-spacing: 22px; + @import "squares/*.png"; + @include all-squares-sprites; + SCSS + assert_correct css, <<-CSS + .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { + background: url('/squares-d66bf24bab.png') no-repeat; + } + + .squares-ten-by-ten { + background-position: 0 0; + } + + .squares-twenty-by-twenty { + background-position: 0 -32px; + } + CSS + assert_equal image_size('squares-*.png'), [20, 52] + end + + it "should use position adjustments in functions" do + css = render <<-SCSS + $squares: sprite-map("squares/*.png", $position: 100%); + .squares-sprite { + background: $squares no-repeat; + } + + .adjusted-percentage { + background-position: sprite-position($squares, ten-by-ten, 100%); + } + + .adjusted-px-1 { + background-position: sprite-position($squares, ten-by-ten, 4px); + } + + .adjusted-px-2 { + background-position: sprite-position($squares, twenty-by-twenty, -3px, 2px); + } + SCSS + assert_correct css, <<-CSS + .squares-sprite { + background: url('/squares-8e490168dd.png') no-repeat; + } + + .adjusted-percentage { + background-position: 100% 0; + } + + .adjusted-px-1 { + background-position: -6px 0; + } + + .adjusted-px-2 { + background-position: -3px -8px; + } + CSS + assert_equal image_size('squares-*.png'), [20, 30] + assert_equal image_md5('squares-*.png'), '652b67f5e9092520d6f26caae7e18012' + end + + it "should use position adjustments in mixins" do + css = render <<-SCSS + $squares-position: 100%; + @import "squares/*.png"; + + .adjusted-percentage { + @include squares-sprite("ten-by-ten", $offset-x: 100%); + } + + .adjusted-px-1 { + @include squares-sprite("ten-by-ten", $offset-x: 4px); + } + + .adjusted-px-2 { + @include squares-sprite("twenty-by-twenty", $offset-x: -3px, $offset-y: 2px); + } + SCSS + assert_correct css, <<-CSS + .squares-sprite, .adjusted-percentage, .adjusted-px-1, .adjusted-px-2 { + background: url('/squares-8e490168dd.png') no-repeat; + } + + .adjusted-percentage { + background-position: 100% 0; + } + + .adjusted-px-1 { + background-position: -6px 0; + } + + .adjusted-px-2 { + background-position: -3px -8px; + } + CSS + assert_equal image_size('squares-*.png'), [20, 30] + assert_equal image_md5('squares-*.png'), '652b67f5e9092520d6f26caae7e18012' + end + + it "should repeat the image" do + css = render <<-SCSS + $squares-repeat: repeat; + @import "squares/*.png"; + @include all-squares-sprites; + SCSS + assert_correct css, <<-CSS + .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { + background: url('/squares-a5550fd132.png') no-repeat; + } + + .squares-ten-by-ten { + background-position: 0 0; + } + + .squares-twenty-by-twenty { + background-position: 0 -10px; + } + CSS + assert_equal image_size('squares-*.png'), [20, 30] + assert_equal image_md5('squares-*.png'), '94abae8440f1b58617f52920b70aaed2' + end + + it "should allow the position of a sprite to be specified in absolute pixels" do + css = render <<-SCSS + $squares-ten-by-ten-position: 10px; + $squares-twenty-by-twenty-position: 10px; + @import "squares/*.png"; + @include all-squares-sprites; + SCSS + assert_correct css, <<-CSS + .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { + background: url('/squares-89a274044e.png') no-repeat; + } + + .squares-ten-by-ten { + background-position: -10px 0; + } + + .squares-twenty-by-twenty { + background-position: -10px -10px; + } + CSS + assert_equal image_size('squares-*.png'), [30, 30] + assert_equal image_md5('squares-*.png'), '2fb19ef9c83018c93c6f147af3a56cb2' + end + + it "should provide a nice errors for lemonade's old users" do + assert_raise(Sass::SyntaxError) do + render <<-SCSS + .squares { + background: sprite-url("squares/*.png") no-repeat; + } + SCSS + end + assert_raise(Sass::SyntaxError) do + css = render <<-SCSS + .squares { + background: sprite-image("squares/twenty-by-twenty.png") no-repeat; + } + SCSS + end + assert_raise(Sass::SyntaxError) do + css = render <<-SCSS + @import "squares/*.png"; + + .squares { + background: sprite-position("squares/twenty-by-twenty.png") no-repeat; + } + SCSS + end + end + + it "should work even if @import is missing" do + css = render <<-SCSS + .squares { + background: sprite(sprite-map("squares/*.png"), twenty-by-twenty) no-repeat; + } + SCSS + assert_correct css, <<-CSS + .squares { + background: url('/squares-145869726f.png') 0 -10px no-repeat; + } + CSS + end + + it "should calculate corret sprite demsions when givin spacing via issue#253" do + css = render <<-SCSS + $squares-spacing: 10px; + @import "squares/*.png"; + .foo { + @include sprite-background-position($squares-sprites, "twenty-by-twenty"); + } + .bar { + @include sprite-background-position($squares-sprites, "ten-by-ten"); + } + SCSS + assert_equal image_size('squares-*.png'), [20, 40] + assert_correct css, <<-CSS + .squares-sprite { + background: url('/squares-e3c68372d9.png') no-repeat; + } + + .foo { + background-position: 0 -20px; + } + + .bar { + background-position: 0 0; + } + CSS + end + + it "should render corret sprite with css selectors via issue#248" do + css = render <<-SCSS + @import "selectors/*.png"; + @include all-selectors-sprites; + SCSS + assert_correct css, <<-CSS + .selectors-sprite, .selectors-ten-by-ten { + background: url('/selectors-edfef809e2.png') no-repeat; + } + + .selectors-ten-by-ten { + background-position: 0 0; + } + .selectors-ten-by-ten:hover, .selectors-ten-by-ten.ten-by-ten_hover, .selectors-ten-by-ten.ten-by-ten-hover { + background-position: 0 -20px; + } + .selectors-ten-by-ten:target, .selectors-ten-by-ten.ten-by-ten_target, .selectors-ten-by-ten.ten-by-ten-target { + background-position: 0 -30px; + } + .selectors-ten-by-ten:active, .selectors-ten-by-ten.ten-by-ten_active, .selectors-ten-by-ten.ten-by-ten-active { + background-position: 0 -10px; + } + CSS + end + + it "should render corret sprite with css selectors via magic mixin" do + css = render <<-SCSS + @import "selectors/*.png"; + a { + @include selectors-sprite(ten-by-ten) + } + SCSS + assert_correct css, <<-CSS + .selectors-sprite, a { + background: url('/selectors-edfef809e2.png') no-repeat; + } + + a { + background-position: 0 0; + } + a:hover, a.ten-by-ten_hover, a.ten-by-ten-hover { + background-position: 0 -20px; + } + a:target, a.ten-by-ten_target, a.ten-by-ten-target { + background-position: 0 -30px; + } + a:active, a.ten-by-ten_active, a.ten-by-ten-active { + background-position: 0 -10px; + } + CSS + end + + it "should not render corret sprite with css selectors via magic mixin" do + css = render <<-SCSS + @import "selectors/*.png"; + a { + $disable-magic-sprite-selectors:true; + @include selectors-sprite(ten-by-ten) + } + SCSS + assert_correct css, <<-CSS + .selectors-sprite, a { + background: url('/selectors-edfef809e2.png') no-repeat; + } + + a { + background-position: 0 0; + } + CSS + end + + it "should raise error on filenames that are not valid sass syntax" do + assert_raise(Compass::Error) do + css = render <<-SCSS + @import "prefix/*.png"; + a { + @include squares-sprite(20-by-20); + } + SCSS + end + end + + it "should generate sprite with bad repeat-x dimensions" do + css = render <<-SCSS + $ko-starbg26x27-repeat: repeat-x; + @import "ko/*.png"; + @include all-ko-sprites; + SCSS + assert_correct css, <<-CSS + .ko-sprite, .ko-default_background, .ko-starbg26x27 { + background: url('/ko-cc3f80660d.png') no-repeat; + } + + .ko-default_background { + background-position: 0 0; + } + + .ko-starbg26x27 { + background-position: 0 -128px; + } + CSS + end + +end \ No newline at end of file From 8e2292b2a595ad52bd4dd8365bfcf3d641d0a327 Mon Sep 17 00:00:00 2001 From: Scott Davis Date: Thu, 28 Apr 2011 00:35:10 -0400 Subject: [PATCH 13/15] sprite base test --- test/sprites/base_test.rb | 73 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 test/sprites/base_test.rb diff --git a/test/sprites/base_test.rb b/test/sprites/base_test.rb new file mode 100644 index 00000000..7205b027 --- /dev/null +++ b/test/sprites/base_test.rb @@ -0,0 +1,73 @@ +require 'test_helper' + +class SpritesBaseTest < Test::Unit::TestCase + + def setup + @images_src_path = File.join(File.dirname(__FILE__), '..', 'fixtures', 'sprites', 'public', 'images') + @images_tmp_path = File.join(File.dirname(__FILE__), '..', 'fixtures', 'sprites', 'public', 'images-tmp') + FileUtils.cp_r @images_src_path, @images_tmp_path + config = Compass::Configuration::Data.new('config') + config.images_path = @images_tmp_path + Compass.add_configuration(config) + Compass.configure_sass_plugin! + options = Compass.sass_engine_options.extend Compass::SassExtensions::Functions::Sprites::VariableReader + @map = Compass::SpriteMap.new("selectors/*.png", options) + @base = Compass::SassExtensions::Sprites::Base.new(@map.sprite_names.map{|n| "selectors/#{n}.png"}, @map.path, 'selectors', @map.sass_engine, @map.options) + end + + def teardown + FileUtils.rm_r @images_tmp_path + end + + it "should have the correct size" do + assert_equal [10,40], @base.size + end + + it "should have the sprite names" do + assert_equal @map.sprite_names, @base.sprite_names + end + + it 'should have image filenames' do + assert_equal Dir["#{@images_tmp_path}/selectors/*.png"].sort, @base.image_filenames + end + + it 'should need generation' do + assert @base.generation_required? + end + + test 'uniqueness_hash' do + assert_equal 'ef52c5c63a', @base.uniqueness_hash + end + + it 'should be outdated' do + assert @base.outdated? + end + + it 'should have correct filename' do + assert_equal File.join(@images_tmp_path, "#{@base.path}-#{@base.uniqueness_hash}.png"), @base.filename + end + + it "should return the 'ten-by-ten' image" do + assert_equal 'ten-by-ten', @base.image_for('ten-by-ten').name + assert @base.image_for('ten-by-ten').is_a?(Compass::SassExtensions::Sprites::Image) + end + + %w(target hover active).each do |selector| + it "should have a #{selector}" do + assert @base.send(:"has_#{selector}?", 'ten-by-ten') + end + + it "should return #{selector} image class" do + assert_equal "ten-by-ten_#{selector}", @base.image_for('ten-by-ten').send(:"#{selector}").name + end + + end + + it "should generate sprite" do + @base.generate + assert File.exists?(@base.filename) + assert !@base.generation_required? + assert !@base.outdated? + end + +end \ No newline at end of file From 1c8804386ae45af9311ffac06f1f5cefc797723d Mon Sep 17 00:00:00 2001 From: Scott Davis Date: Thu, 28 Apr 2011 02:49:03 -0400 Subject: [PATCH 14/15] more sprite tests to test_unit --- test/sprites/image_test.rb | 96 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 test/sprites/image_test.rb diff --git a/test/sprites/image_test.rb b/test/sprites/image_test.rb new file mode 100644 index 00000000..8ac98c52 --- /dev/null +++ b/test/sprites/image_test.rb @@ -0,0 +1,96 @@ +require 'test_helper' +require 'mocha' +require 'ostruct' +class SpritesImageTest < Test::Unit::TestCase + + + def setup + @images_src_path = File.join(File.dirname(__FILE__), '..', 'fixtures', 'sprites', 'public', 'images') + file = StringIO.new("images_path = #{@images_src_path.inspect}\n") + Compass.add_configuration(file, "sprite_config") + @repeat = 'no-repeat' + @spacing = 0 + @position = 100 + @offset = 100 + end + + let(:sprite_filename) { 'squares/ten-by-ten.png' } + let(:sprite_path) { File.join(@images_src_path, sprite_filename) } + let(:sprite_name) { File.basename(sprite_filename, '.png') } + def parent + map = Compass::SpriteMap.new("selectors/*.png", options) + @parent ||= Compass::SassExtensions::Sprites::Base.new(map.sprite_names.map{|n| "selectors/#{n}.png"}, map, map.sass_engine, map.options) + end + + let(:options) do + options = {:offset => @offset} + options.stubs(:get_var).with(anything).returns(nil) + ::OpenStruct.any_instance.stubs(:unitless?).returns(true) + options.stubs(:get_var).with("#{sprite_name}-repeat").returns(::OpenStruct.new(:value => @repeat)) + options.stubs(:get_var).with("#{sprite_name}-spacing").returns(::OpenStruct.new(:value => @spacing)) + options.stubs(:get_var).with("#{sprite_name}-position").returns(::OpenStruct.new(:value => @position)) + options + end + + + + let(:digest) { Digest::MD5.file(sprite_path).hexdigest } + + + let(:image) { Compass::SassExtensions::Sprites::Image.new(parent, File.join(sprite_filename), options)} + + test 'initialize' do + assert_equal sprite_name, image.name + assert_equal sprite_path, image.file + assert_equal sprite_filename, image.relative_file + assert_equal 10, image.width + assert_equal 10, image.height + assert_equal digest, image.digest + assert_equal 0, image.top + assert_equal 0, image.left + end + + test 'hover' do + assert_equal 'ten-by-ten_hover', image.hover.name + end + + test 'no parent' do + assert_nil image.parent + end + + test 'image type is nil' do + @repeat = nil + assert_nil image.repeat + end + + + test 'image type is "global"' do + @repeat = 'global' + assert_equal @repeat, image.repeat + end + + test 'image type is "no-repeat"' do + assert_equal 'no-repeat', image.repeat + end + + test 'image position' do + assert_equal Sass::Script::Number.new(100, ["px"]).value, image.position.value + end + + test 'image spacing' do + @spacing = 10 + assert_equal @spacing, image.spacing + end + + test 'offset' do + assert_equal @offset, image.offset + end + + test 'neither, uses 0' do + @offset = 0 + img = image + img.position.stubs(:unitless?).returns(false) + assert_equal 0, img.offset + end + +end From 5a2967fe51e713221482a46ae89b3c5b119ce06f Mon Sep 17 00:00:00 2001 From: Scott Davis Date: Thu, 28 Apr 2011 02:50:14 -0400 Subject: [PATCH 15/15] sprite test_unit --- Gemfile.lock | 2 +- lib/compass/sass_extensions/sprites/base.rb | 9 +++++---- test/helpers/test_case.rb | 4 ++++ test/sprites/base_test.rb | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index fd728c5c..33b44d66 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,7 +7,7 @@ GIT PATH remote: . specs: - compass (0.11.1.f4f9d7b) + compass (0.11.1.8e2292b) chunky_png (~> 1.1) fssm (>= 0.2.7) sass (~> 3.1) diff --git a/lib/compass/sass_extensions/sprites/base.rb b/lib/compass/sass_extensions/sprites/base.rb index aa671b39..194a5601 100644 --- a/lib/compass/sass_extensions/sprites/base.rb +++ b/lib/compass/sass_extensions/sprites/base.rb @@ -12,7 +12,7 @@ module Compass sprites = sprite_map.files.map do |sprite| sprite.gsub(Compass.configuration.images_path+"/", "") end - new(sprites, sprite_map.path, sprite_map.name, context, kwargs) + new(sprites, sprite_map, context, kwargs) end # Loads the sprite engine @@ -24,17 +24,18 @@ module Compass # We should do so only when the packing algorithm changes SPRITE_VERSION = "1" - attr_accessor :image_names, :path, :name, :options + attr_accessor :image_names, :path, :name, :options, :map attr_accessor :images, :width, :height - def initialize(image_names, path, name, context, options) + def initialize(image_names, map, context, options) require_engine! - @image_names, @path, @name, @options = image_names, path, name, options + @image_names, @path, @name, @options = image_names, map.path, map.name, options @images = nil @width = nil @height = nil @evaluation_context = context + @map = map validate! compute_image_metadata! end diff --git a/test/helpers/test_case.rb b/test/helpers/test_case.rb index 530ba59e..08922e02 100644 --- a/test/helpers/test_case.rb +++ b/test/helpers/test_case.rb @@ -20,6 +20,10 @@ module Compass module ClassMethods + def let(method, &block) + define_method method, &block + end + def it(name, &block) test(name, &block) end diff --git a/test/sprites/base_test.rb b/test/sprites/base_test.rb index 7205b027..a5c0adef 100644 --- a/test/sprites/base_test.rb +++ b/test/sprites/base_test.rb @@ -12,7 +12,7 @@ class SpritesBaseTest < Test::Unit::TestCase Compass.configure_sass_plugin! options = Compass.sass_engine_options.extend Compass::SassExtensions::Functions::Sprites::VariableReader @map = Compass::SpriteMap.new("selectors/*.png", options) - @base = Compass::SassExtensions::Sprites::Base.new(@map.sprite_names.map{|n| "selectors/#{n}.png"}, @map.path, 'selectors', @map.sass_engine, @map.options) + @base = Compass::SassExtensions::Sprites::Base.new(@map.sprite_names.map{|n| "selectors/#{n}.png"}, @map, @map.sass_engine, @map.options) end def teardown