JezK
Edit File: conversion_test.rb
#!/usr/bin/env ruby require File.dirname(__FILE__) + '/../test_helper' class ConversionTest < Test::Unit::TestCase def test_basic assert_renders <<SASS, <<SCSS foo bar baz: bang bip: bop SASS foo bar { baz: bang; bip: bop; } SCSS assert_renders <<SASS, <<SCSS, :old => true foo bar :baz bang :bip bop SASS foo bar { baz: bang; bip: bop; } SCSS end def test_empty_selector assert_renders "foo bar", "foo bar {}" end def test_empty_directive assert_scss_to_sass "@media screen", "@media screen {}" assert_scss_to_scss "@media screen {}" end def test_empty_control_directive assert_renders "@if false", "@if false {}" end def test_nesting assert_renders <<SASS, <<SCSS foo bar baz bang baz: bang bip: bop blat: boo SASS foo bar { baz bang { baz: bang; bip: bop; } blat: boo; } SCSS end def test_nesting_with_parent_ref assert_renders <<SASS, <<SCSS foo bar &:hover baz: bang SASS foo bar { &:hover { baz: bang; } } SCSS end def test_selector_interpolation assert_renders <<SASS, <<SCSS foo \#{$bar + "baz"}.bip baz: bang SASS foo \#{$bar + "baz"}.bip { baz: bang; } SCSS end def test_multiline_selector_with_commas assert_renders <<SASS, <<SCSS foo bar, baz bang baz: bang SASS foo bar, baz bang { baz: bang; } SCSS assert_renders <<SASS, <<SCSS blat foo bar, baz bang baz: bang SASS blat { foo bar, baz bang { baz: bang; } } SCSS end def test_multiline_selector_without_commas assert_scss_to_sass <<SASS, <<SCSS foo bar baz bang baz: bang SASS foo bar baz bang { baz: bang; } SCSS assert_scss_to_scss <<SCSS foo bar baz bang { baz: bang; } SCSS end def test_escaped_selector assert_renders <<SASS, <<SCSS foo bar \\:hover baz: bang SASS foo bar { :hover { baz: bang; } } SCSS end def test_property_name_interpolation assert_renders <<SASS, <<SCSS foo bar baz\#{$bang}bip\#{$bop}: 12 SASS foo bar { baz\#{$bang}bip\#{$bop}: 12; } SCSS end def test_property_name_interpolation assert_renders <<SASS, <<SCSS foo bar baz\#{$bang}bip\#{$bop}: 12 SASS foo bar { baz\#{$bang}bip\#{$bop}: 12; } SCSS end def test_property_value_interpolation assert_renders <<SASS, <<SCSS foo bar baz: 12 \#{$bang} bip \#{"bop"} blat SASS foo bar { baz: 12 \#{$bang} bip \#{"bop"} blat; } SCSS end def test_dynamic_properties assert_renders <<SASS, <<SCSS foo bar baz: 12 $bang "bip" SASS foo bar { baz: 12 $bang "bip"; } SCSS end def test_dynamic_properties_with_old assert_renders <<SASS, <<SCSS, :old => true foo bar :baz 12 $bang "bip" SASS foo bar { baz: 12 $bang "bip"; } SCSS end def test_multiline_properties assert_scss_to_sass <<SASS, <<SCSS foo bar baz: bip bam boon SASS foo bar { baz: bip bam boon; } SCSS assert_scss_to_scss <<OUT, <<IN foo bar { baz: bip bam boon; } OUT foo bar { baz: bip bam boon; } IN end def test_multiline_dynamic_properties assert_scss_to_sass <<SASS, <<SCSS foo bar baz: $bip "bam" 12px SASS foo bar { baz: $bip "bam" 12px; } SCSS assert_scss_to_scss <<OUT, <<IN foo bar { baz: $bip "bam" 12px; } OUT foo bar { baz: $bip "bam" 12px; } IN end def test_silent_comments assert_renders <<SASS, <<SCSS // foo // bar // baz foo bar a: b SASS // foo // bar // baz foo bar { a: b; } SCSS assert_renders <<SASS, <<SCSS // foo // bar // baz // bang foo bar a: b SASS // foo // bar // baz // bang foo bar { a: b; } SCSS assert_sass_to_scss <<SCSS, <<SASS // foo // bar // baz // bang foo bar { a: b; } SCSS // foo // bar // baz // bang foo bar a: b SASS end def test_nested_silent_comments assert_renders <<SASS, <<SCSS foo bar: baz // bip bop // beep boop bang: bizz // bubble bubble // toil trouble SASS foo { bar: baz; // bip bop // beep boop bang: bizz; // bubble bubble // toil trouble } SCSS assert_sass_to_scss <<SCSS, <<SASS foo { bar: baz; // bip bop // beep boop // bap blimp bang: bizz; // bubble bubble // toil trouble // gorp } SCSS foo bar: baz // bip bop beep boop bap blimp bang: bizz // bubble bubble toil trouble gorp SASS end def test_loud_comments assert_renders <<SASS, <<SCSS /* foo /* bar /* baz foo bar a: b SASS /* foo */ /* bar */ /* baz */ foo bar { a: b; } SCSS assert_scss_to_sass <<SASS, <<SCSS /* foo * bar * baz * bang foo bar a: b SASS /* foo bar baz bang */ foo bar { a: b; } SCSS assert_scss_to_scss <<SCSS /* foo bar baz bang */ foo bar { a: b; } SCSS assert_renders <<SASS, <<SCSS /* foo * bar * baz * bang foo bar a: b SASS /* foo * bar * baz * bang */ foo bar { a: b; } SCSS end def test_nested_loud_comments assert_renders <<SASS, <<SCSS foo bar: baz /* bip bop * beep boop bang: bizz /* bubble bubble * toil trouble SASS foo { bar: baz; /* bip bop * beep boop */ bang: bizz; /* bubble bubble * toil trouble */ } SCSS assert_sass_to_scss <<SCSS, <<SASS foo { bar: baz; /* bip bop * beep boop * bap blimp */ bang: bizz; /* bubble bubble * toil trouble * gorp */ } SCSS foo bar: baz /* bip bop beep boop bap blimp bang: bizz /* bubble bubble toil trouble gorp SASS end def test_loud_comments_with_weird_indentation assert_scss_to_sass <<SASS, <<SCSS foo /* foo * bar * baz a: b SASS foo { /* foo bar baz */ a: b; } SCSS assert_sass_to_scss <<SCSS, <<SASS foo { /* foo * bar * baz */ a: b; } SCSS foo /* foo bar baz a: b SASS end def test_immediately_preceding_comments assert_renders <<SASS, <<SCSS /* Foo * Bar * Baz .foo#bar a: b SASS /* Foo * Bar * Baz */ .foo#bar { a: b; } SCSS assert_renders <<SASS, <<SCSS // Foo // Bar // Baz =foo a: b SASS // Foo // Bar // Baz @mixin foo { a: b; } SCSS end def test_debug assert_renders <<SASS, <<SCSS foo @debug 12px bar: baz SASS foo { @debug 12px; bar: baz; } SCSS end def test_directive_without_children assert_renders <<SASS, <<SCSS foo @foo #bar "baz" bar: baz SASS foo { @foo #bar "baz"; bar: baz; } SCSS end def test_directive_with_prop_children assert_renders <<SASS, <<SCSS foo @foo #bar "baz" a: b c: d bar: baz SASS foo { @foo #bar "baz" { a: b; c: d; } bar: baz; } SCSS end def test_directive_with_rule_children assert_renders <<SASS, <<SCSS foo @foo #bar "baz" #blat a: b .bang c: d e: f bar: baz SASS foo { @foo #bar "baz" { #blat { a: b; } .bang { c: d; e: f; } } bar: baz; } SCSS end def test_directive_with_rule_and_prop_children assert_renders <<SASS, <<SCSS foo @foo #bar "baz" g: h #blat a: b .bang c: d e: f i: j bar: baz SASS foo { @foo #bar "baz" { g: h; #blat { a: b; } .bang { c: d; e: f; } i: j; } bar: baz; } SCSS end def test_charset assert_renders <<SASS, <<SCSS @charset "utf-8" SASS @charset "utf-8"; SCSS end def test_for assert_renders <<SASS, <<SCSS foo @for $a from $b to $c a: b @for $c from 1 to 16 d: e f: g SASS foo { @for $a from $b to $c { a: b; } @for $c from 1 to 16 { d: e; f: g; } } SCSS end def test_while assert_renders <<SASS, <<SCSS foo @while flaz($a + $b) a: b @while 1 d: e f: g SASS foo { @while flaz($a + $b) { a: b; } @while 1 { d: e; f: g; } } SCSS end def test_if assert_renders <<SASS, <<SCSS foo @if $foo or $bar a: b @if $baz d: e @else if $bang f: g @else h: i SASS foo { @if $foo or $bar { a: b; } @if $baz { d: e; } @else if $bang { f: g; } @else { h: i; } } SCSS end def test_each assert_renders <<SASS, <<SCSS a @each $number in 1px 2px 3px 4px b: $number c @each $str in foo, bar, baz, bang d: $str SASS a { @each $number in 1px 2px 3px 4px { b: $number; } } c { @each $str in foo, bar, baz, bang { d: $str; } } SCSS end def test_import assert_renders <<SASS, <<SCSS @import foo @import url(bar.css) foo bar: baz SASS @import "foo"; @import url(bar.css); foo { bar: baz; } SCSS assert_renders <<SASS, <<SCSS @import foo.css @import url(bar.css) foo bar: baz SASS @import "foo.css"; @import url(bar.css); foo { bar: baz; } SCSS end def test_import_as_directive_in_sass assert_equal "@import foo.css\n", to_sass('@import "foo.css"') end def test_import_as_directive_in_scss assert_renders <<SASS, <<SCSS @import "foo.css" print SASS @import "foo.css" print; SCSS assert_renders <<SASS, <<SCSS @import url(foo.css) screen, print SASS @import url(foo.css) screen, print; SCSS end def test_adjacent_imports assert_renders <<SASS, <<SCSS @import foo.sass @import bar.scss @import baz SASS @import "foo.sass"; @import "bar.scss"; @import "baz"; SCSS end def test_non_adjacent_imports assert_renders <<SASS, <<SCSS @import foo.sass @import bar.scss @import baz SASS @import "foo.sass"; @import "bar.scss"; @import "baz"; SCSS end def test_extend assert_renders <<SASS, <<SCSS .foo @extend .bar @extend .baz:bang SASS .foo { @extend .bar; @extend .baz:bang; } SCSS end def test_comma_extendee assert_renders <<SASS, <<SCSS .baz @extend .foo, .bar SASS .baz { @extend .foo, .bar; } SCSS end def test_argless_mixin_definition assert_renders <<SASS, <<SCSS =foo-bar baz a: b SASS @mixin foo-bar { baz { a: b; } } SCSS assert_scss_to_sass <<SASS, <<SCSS =foo-bar baz a: b SASS @mixin foo-bar() { baz { a: b; } } SCSS assert_sass_to_scss <<SCSS, <<SASS @mixin foo-bar { baz { a: b; } } SCSS =foo-bar() baz a: b SASS end def test_mixin_definition_without_defaults assert_renders <<SASS, <<SCSS =foo-bar($baz, $bang) baz a: $baz $bang SASS @mixin foo-bar($baz, $bang) { baz { a: $baz $bang; } } SCSS end def test_mixin_definition_with_defaults assert_renders <<SASS, <<SCSS =foo-bar($baz, $bang: 12px) baz a: $baz $bang SASS @mixin foo-bar($baz, $bang: 12px) { baz { a: $baz $bang; } } SCSS assert_sass_to_scss <<SCSS, <<SASS @mixin foo-bar($baz, $bang: foo) { baz { a: $baz $bang; } } SCSS =foo-bar($baz, $bang: foo) baz a: $baz $bang SASS end def test_argless_mixin_include assert_renders <<SASS, <<SCSS foo +foo-bar a: blip SASS foo { @include foo-bar; a: blip; } SCSS end def test_mixin_include assert_renders <<SASS, <<SCSS foo +foo-bar(12px, "blaz") a: blip SASS foo { @include foo-bar(12px, "blaz"); a: blip; } SCSS end def test_mixin_include_with_keyword_args assert_renders <<SASS, <<SCSS foo +foo-bar(12px, "blaz", $blip: blap, $bloop: blop) +foo-bar($blip: blap, $bloop: blop) a: blip SASS foo { @include foo-bar(12px, "blaz", $blip: blap, $bloop: blop); @include foo-bar($blip: blap, $bloop: blop); a: blip; } SCSS end def test_argless_function_definition assert_renders <<SASS, <<SCSS @function foo() $var: 1 + 1 @return $var SASS @function foo() { $var: 1 + 1; @return $var; } SCSS end def test_function_definition_without_defaults assert_renders <<SASS, <<SCSS @function foo($var1, $var2) @if $var1 @return $var1 + $var2 SASS @function foo($var1, $var2) { @if $var1 { @return $var1 + $var2; } } SCSS end def test_function_definition_with_defaults assert_renders <<SASS, <<SCSS @function foo($var1, $var2: foo) @if $var1 @return $var1 + $var2 SASS @function foo($var1, $var2: foo) { @if $var1 { @return $var1 + $var2; } } SCSS end def test_variable_definition assert_renders <<SASS, <<SCSS $var1: 12px + 15px foo $var2: flaz(#abcdef) val: $var1 $var2 SASS $var1: 12px + 15px; foo { $var2: flaz(#abcdef); val: $var1 $var2; } SCSS end def test_guarded_variable_definition assert_renders <<SASS, <<SCSS $var1: 12px + 15px !default foo $var2: flaz(#abcdef) !default val: $var1 $var2 SASS $var1: 12px + 15px !default; foo { $var2: flaz(#abcdef) !default; val: $var1 $var2; } SCSS end def test_multiple_variable_definitions assert_renders <<SASS, <<SCSS $var1: foo $var2: bar $var3: baz $var4: bip $var5: bap SASS $var1: foo; $var2: bar; $var3: baz; $var4: bip; $var5: bap; SCSS end def test_division_asserted_with_parens assert_renders <<SASS, <<SCSS foo a: (1px / 2px) SASS foo { a: (1px / 2px); } SCSS end def test_division_not_asserted_when_unnecessary assert_renders <<SASS, <<SCSS $var: 1px / 2px foo a: $var SASS $var: 1px / 2px; foo { a: $var; } SCSS assert_renders <<SASS, <<SCSS $var: 1px foo a: $var / 2px SASS $var: 1px; foo { a: $var / 2px; } SCSS assert_renders <<SASS, <<SCSS foo a: 1 + 1px / 2px SASS foo { a: 1 + 1px / 2px; } SCSS end def test_literal_slash assert_renders <<SASS, <<SCSS foo a: 1px / 2px SASS foo { a: 1px / 2px; } SCSS end # Hacks def test_declaration_hacks assert_renders <<SASS, <<SCSS foo _name: val *name: val #name: val .name: val name/**/: val name/*\\**/: val name: val SASS foo { _name: val; *name: val; #name: val; .name: val; name/**/: val; name/*\\**/: val; name: val; } SCSS end def test_old_declaration_hacks assert_renders <<SASS, <<SCSS, :old => true foo :_name val :*name val :#name val :.name val :name val SASS foo { _name: val; *name: val; #name: val; .name: val; name: val; } SCSS end def test_selector_hacks assert_selector_renders = lambda do |s| assert_renders <<SASS, <<SCSS #{s} a: b SASS #{s} { a: b; } SCSS end assert_selector_renders['> E'] assert_selector_renders['+ E'] assert_selector_renders['~ E'] assert_selector_renders['> > E'] assert_selector_renders['E*'] assert_selector_renders['E*.foo'] assert_selector_renders['E*:hover'] end def test_disallowed_colon_hack assert_raise_message(Sass::SyntaxError, 'The ":name: val" hack is not allowed in the Sass indented syntax') do to_sass("foo {:name: val;}", :syntax => :scss) end end def test_nested_properties assert_renders <<SASS, <<SCSS div before: before background: color: blue repeat: no-repeat after: after SASS div { before: before; background: { color: blue; repeat: no-repeat; }; after: after; } SCSS end def test_dasherize assert_sass_to_scss(<<SCSS, <<SASS, :dasherize => true) @mixin under-scored-mixin($under-scored-arg: $under-scored-default) { bar: $under-scored-arg; } div { foo: under-scored-fn($under-scored-var + "before\#{$another-under-scored-var}after"); @include under-scored-mixin($passed-arg); selector-\#{$under-scored-interp}: bold; } @if $under-scored { @for $for-var from $from-var to $to-var { @while $while-var == true { $while-var: false; } } } SCSS =under_scored_mixin($under_scored_arg: $under_scored_default) bar: $under_scored_arg div foo: under_scored_fn($under_scored_var + "before\#{$another_under_scored_var}after") +under_scored_mixin($passed_arg) selector-\#{$under_scored_interp}: bold @if $under_scored @for $for_var from $from_var to $to_var @while $while_var == true $while_var : false SASS end def test_loud_comment_conversion assert_renders(<<SASS, <<SCSS) /*! \#{"interpolated"} SASS /*! \#{"interpolated"} */ SCSS silence_warnings {assert_renders(<<SASS, <<SCSS)} //! \#{"interpolated"} //! //! \#{"also interpolated"} SASS //! \#{"interpolated"} //! //! \#{"also interpolated"} SCSS end ## Regression Tests def test_empty_lists assert_renders(<<SASS, <<SCSS) $foo: () SASS $foo: (); SCSS end def test_nested_if_statements assert_renders(<<SASS, <<SCSS) @if $foo one a: b @else @if $bar two a: b @else three a: b SASS @if $foo { one { a: b; } } @else { @if $bar { two { a: b; } } @else { three { a: b; } } } SCSS end private def assert_sass_to_sass(sass, options = {}) assert_equal(sass.rstrip, to_sass(sass, options).rstrip, "Expected Sass to transform to itself") end def assert_scss_to_sass(sass, scss, options = {}) assert_equal(sass.rstrip, to_sass(scss, options.merge(:syntax => :scss)).rstrip, "Expected SCSS to transform to Sass") end def assert_scss_to_scss(scss, in_scss = nil, options = nil) if in_scss.is_a?(Hash) options = in_scss in_scss = nil end in_scss ||= scss options ||= {} assert_equal(scss.rstrip, to_scss(in_scss, options.merge(:syntax => :scss)).rstrip, "Expected SCSS to transform to #{scss == in_scss ? 'itself' : 'SCSS'}k") end def assert_sass_to_scss(scss, sass, options = {}) assert_equal(scss.rstrip, to_scss(sass, options).rstrip, "Expected Sass to transform to SCSS") end def assert_renders(sass, scss, options = {}) assert_sass_to_sass(sass, options) assert_scss_to_sass(sass, scss, options) assert_scss_to_scss(scss, options) assert_sass_to_scss(scss, sass, options) end def to_sass(scss, options = {}) Sass::Util.silence_sass_warnings do Sass::Engine.new(scss, options).to_tree.to_sass(options) end end def to_scss(sass, options = {}) Sass::Util.silence_sass_warnings do Sass::Engine.new(sass, options).to_tree.to_scss(options) end end end