haml 3.0.0.beta.3 → 3.0.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of haml might be problematic. Click here for more details.

Files changed (82) hide show
  1. data/.yardopts +2 -0
  2. data/REMEMBER +4 -11
  3. data/Rakefile +24 -2
  4. data/VERSION +1 -1
  5. data/lib/haml.rb +5 -2
  6. data/lib/haml/exec.rb +11 -4
  7. data/lib/haml/filters.rb +3 -0
  8. data/lib/haml/helpers.rb +2 -10
  9. data/lib/haml/helpers/action_view_extensions.rb +4 -2
  10. data/lib/haml/helpers/action_view_mods.rb +6 -4
  11. data/lib/haml/html.rb +0 -1
  12. data/lib/haml/precompiler.rb +37 -30
  13. data/lib/haml/railtie.rb +6 -2
  14. data/lib/haml/root.rb +4 -0
  15. data/lib/haml/template.rb +2 -0
  16. data/lib/haml/util.rb +74 -0
  17. data/lib/haml/util/subset_map.rb +101 -0
  18. data/lib/sass.rb +1 -0
  19. data/lib/sass/engine.rb +36 -31
  20. data/lib/sass/files.rb +1 -1
  21. data/lib/sass/plugin.rb +21 -0
  22. data/lib/sass/plugin/staleness_checker.rb +9 -9
  23. data/lib/sass/script.rb +1 -2
  24. data/lib/sass/script/color.rb +4 -3
  25. data/lib/sass/script/css_lexer.rb +11 -1
  26. data/lib/sass/script/css_parser.rb +4 -1
  27. data/lib/sass/script/funcall.rb +9 -0
  28. data/lib/sass/script/interpolation.rb +21 -0
  29. data/lib/sass/script/lexer.rb +30 -13
  30. data/lib/sass/script/node.rb +1 -1
  31. data/lib/sass/script/number.rb +4 -5
  32. data/lib/sass/script/parser.rb +13 -14
  33. data/lib/sass/script/string.rb +8 -2
  34. data/lib/sass/script/string_interpolation.rb +27 -4
  35. data/lib/sass/scss.rb +3 -0
  36. data/lib/sass/scss/css_parser.rb +5 -3
  37. data/lib/sass/scss/parser.rb +146 -64
  38. data/lib/sass/scss/rx.rb +9 -1
  39. data/lib/sass/scss/sass_parser.rb +11 -0
  40. data/lib/sass/scss/script_lexer.rb +2 -0
  41. data/lib/sass/scss/static_parser.rb +48 -0
  42. data/lib/sass/selector.rb +353 -0
  43. data/lib/sass/selector/abstract_sequence.rb +40 -0
  44. data/lib/sass/selector/comma_sequence.rb +80 -0
  45. data/lib/sass/selector/sequence.rb +194 -0
  46. data/lib/sass/selector/simple.rb +107 -0
  47. data/lib/sass/selector/simple_sequence.rb +161 -0
  48. data/lib/sass/tree/comment_node.rb +1 -0
  49. data/lib/sass/tree/debug_node.rb +1 -0
  50. data/lib/sass/tree/directive_node.rb +1 -0
  51. data/lib/sass/tree/extend_node.rb +60 -0
  52. data/lib/sass/tree/for_node.rb +1 -0
  53. data/lib/sass/tree/if_node.rb +2 -0
  54. data/lib/sass/tree/import_node.rb +2 -0
  55. data/lib/sass/tree/mixin_def_node.rb +1 -0
  56. data/lib/sass/tree/mixin_node.rb +21 -5
  57. data/lib/sass/tree/node.rb +59 -12
  58. data/lib/sass/tree/prop_node.rb +20 -21
  59. data/lib/sass/tree/root_node.rb +8 -17
  60. data/lib/sass/tree/rule_node.rb +49 -100
  61. data/lib/sass/tree/variable_node.rb +1 -0
  62. data/lib/sass/tree/warn_node.rb +1 -0
  63. data/lib/sass/tree/while_node.rb +1 -0
  64. data/test/haml/engine_test.rb +185 -3
  65. data/test/haml/helper_test.rb +25 -2
  66. data/test/haml/template_test.rb +2 -2
  67. data/test/haml/templates/helpers.haml +13 -0
  68. data/test/haml/util/subset_map_test.rb +91 -0
  69. data/test/haml/util_test.rb +25 -0
  70. data/test/sass/conversion_test.rb +23 -3
  71. data/test/sass/engine_test.rb +50 -7
  72. data/test/sass/extend_test.rb +1045 -0
  73. data/test/sass/results/complex.css +0 -1
  74. data/test/sass/results/script.css +1 -1
  75. data/test/sass/script_conversion_test.rb +16 -0
  76. data/test/sass/script_test.rb +37 -4
  77. data/test/sass/scss/css_test.rb +17 -3
  78. data/test/sass/scss/rx_test.rb +1 -1
  79. data/test/sass/scss/scss_test.rb +30 -0
  80. data/test/sass/templates/complex.sass +0 -2
  81. data/test/test_helper.rb +5 -0
  82. metadata +18 -4
@@ -15,7 +15,18 @@ module Haml::Helpers
15
15
  end
16
16
 
17
17
  class HelperTest < Test::Unit::TestCase
18
- Post = Struct.new('Post', :body)
18
+ Post = Struct.new('Post', :body, :error_field, :errors)
19
+ class PostErrors
20
+ def on(name)
21
+ return unless name == 'error_field'
22
+ ["Really bad error"]
23
+ end
24
+ alias_method :full_messages, :on
25
+
26
+ def [](name)
27
+ on(name) || []
28
+ end
29
+ end
19
30
 
20
31
  def setup
21
32
  @base = ActionView::Base.new
@@ -26,7 +37,7 @@ class HelperTest < Test::Unit::TestCase
26
37
  @base.controller.response = ActionController::Response.new
27
38
  end
28
39
 
29
- @base.instance_variable_set('@post', Post.new("Foo bar\nbaz"))
40
+ @base.instance_variable_set('@post', Post.new("Foo bar\nbaz", nil, PostErrors.new))
30
41
  end
31
42
 
32
43
  def render(text, options = {})
@@ -153,6 +164,18 @@ HTML
153
164
  HAML
154
165
  end
155
166
 
167
+ def test_content_tag_error_wrapping
168
+ def @base.protect_against_forgery?; false; end
169
+ assert_equal(<<HTML, render(<<HAML, :action_view))
170
+ <form action="" method="post">
171
+ <div class="fieldWithErrors"><label for="post_error_field">Error field</label></div>
172
+ </form>
173
+ HTML
174
+ #{rails_block_helper_char} form_for #{form_for_calling_convention('post')}, :url => '' do |f|
175
+ = f.label 'error_field'
176
+ HAML
177
+ end
178
+
156
179
  def test_haml_tag_name_attribute_with_id
157
180
  assert_equal("<p id='some_id'></p>\n", render("- haml_tag 'p#some_id'"))
158
181
  end
@@ -288,7 +288,7 @@ END
288
288
  <input id="article_body" name="article[body]" size="30" type="text" value="World" />
289
289
  </form>
290
290
  HTML
291
- - form_for :article, @article, :url => '' do |f|
291
+ - form_for #{form_for_calling_convention(:article)}, :url => '' do |f|
292
292
  Title:
293
293
  = f.text_field :title
294
294
  Body:
@@ -387,7 +387,7 @@ HAML
387
387
  <input id="article_body" name="article[body]" size="30" type="text" value="World" />
388
388
  </form>
389
389
  HTML
390
- #{rails_block_helper_char} form_for :article, @article, :url => '' do |f|
390
+ #{rails_block_helper_char} form_for #{form_for_calling_convention(:article)}, :url => '' do |f|
391
391
  Title:
392
392
  = f.text_field :title
393
393
  Body:
@@ -62,6 +62,19 @@ click
62
62
  <input id="article_body" name="article[body]" size="30" type="text" value="World" />
63
63
  </form>
64
64
  </div>
65
+ - elsif Haml::Util.ap_geq_3_beta_3?
66
+ %p
67
+ = form_tag ''
68
+ %div
69
+ = form_tag '' do
70
+ %div= submit_tag 'save'
71
+ - @foo = 'value one'
72
+ = test_partial 'partial'
73
+ = form_for @article, :as => :article, :url => '', :html => {:class => nil, :id => nil} do |f|
74
+ Title:
75
+ = f.text_field :title
76
+ Body:
77
+ = f.text_field :body
65
78
  - elsif Haml::Util.ap_geq_3?
66
79
  %p
67
80
  = form_tag ''
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../../test_helper'
3
+
4
+ class SubsetMapTest < Test::Unit::TestCase
5
+ def setup
6
+ @ssm = Haml::Util::SubsetMap.new
7
+ @ssm[Set[1, 2]] = "Foo"
8
+ @ssm[Set["fizz", "fazz"]] = "Bar"
9
+
10
+ @ssm[Set[:foo, :bar]] = "Baz"
11
+ @ssm[Set[:foo, :bar, :baz]] = "Bang"
12
+
13
+ @ssm[Set[:bip, :bop, :blip]] = "Qux"
14
+ @ssm[Set[:bip, :bop]] = "Thram"
15
+ end
16
+
17
+ def test_equal_keys
18
+ assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[1, 2])
19
+ assert_equal [["Bar", Set["fizz", "fazz"]]], @ssm.get(Set["fizz", "fazz"])
20
+ end
21
+
22
+ def test_subset_keys
23
+ assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[1, 2, "fuzz"])
24
+ assert_equal [["Bar", Set["fizz", "fazz"]]], @ssm.get(Set["fizz", "fazz", 3])
25
+ end
26
+
27
+ def test_superset_keys
28
+ assert_equal [], @ssm.get(Set[1])
29
+ assert_equal [], @ssm.get(Set[2])
30
+ assert_equal [], @ssm.get(Set["fizz"])
31
+ assert_equal [], @ssm.get(Set["fazz"])
32
+ end
33
+
34
+ def test_disjoint_keys
35
+ assert_equal [], @ssm.get(Set[3, 4])
36
+ assert_equal [], @ssm.get(Set["fuzz", "frizz"])
37
+ assert_equal [], @ssm.get(Set["gran", 15])
38
+ end
39
+
40
+ def test_semi_disjoint_keys
41
+ assert_equal [], @ssm.get(Set[2, 3])
42
+ assert_equal [], @ssm.get(Set["fizz", "fuzz"])
43
+ assert_equal [], @ssm.get(Set[1, "fazz"])
44
+ end
45
+
46
+ def test_empty_key_set
47
+ assert_raise(ArgumentError) {@ssm[Set[]] = "Fail"}
48
+ end
49
+
50
+ def test_empty_key_get
51
+ assert_equal [], @ssm.get(Set[])
52
+ end
53
+
54
+ def test_multiple_subsets
55
+ assert_equal [["Foo", Set[1, 2]], ["Bar", Set["fizz", "fazz"]]], @ssm.get(Set[1, 2, "fizz", "fazz"])
56
+ assert_equal [["Foo", Set[1, 2]], ["Bar", Set["fizz", "fazz"]]], @ssm.get(Set[1, 2, 3, "fizz", "fazz", "fuzz"])
57
+
58
+ assert_equal [["Baz", Set[:foo, :bar]]], @ssm.get(Set[:foo, :bar])
59
+ assert_equal [["Baz", Set[:foo, :bar]], ["Bang", Set[:foo, :bar, :baz]]], @ssm.get(Set[:foo, :bar, :baz])
60
+ end
61
+
62
+ def test_bracket_bracket
63
+ assert_equal ["Foo"], @ssm[Set[1, 2, "fuzz"]]
64
+ assert_equal ["Baz", "Bang"], @ssm[Set[:foo, :bar, :baz]]
65
+ end
66
+
67
+ def test_order_preserved
68
+ @ssm[Set[10, 11, 12]] = 1
69
+ @ssm[Set[10, 11]] = 2
70
+ @ssm[Set[11]] = 3
71
+ @ssm[Set[11, 12]] = 4
72
+ @ssm[Set[9, 10, 11, 12, 13]] = 5
73
+ @ssm[Set[10, 13]] = 6
74
+
75
+ assert_equal(
76
+ [[1, Set[10, 11, 12]], [2, Set[10, 11]], [3, Set[11]], [4, Set[11, 12]],
77
+ [5, Set[9, 10, 11, 12, 13]], [6, Set[10, 13]]],
78
+ @ssm.get(Set[9, 10, 11, 12, 13]))
79
+ end
80
+
81
+ def test_multiple_equal_values
82
+ @ssm[Set[11, 12]] = 1
83
+ @ssm[Set[12, 13]] = 2
84
+ @ssm[Set[13, 14]] = 1
85
+ @ssm[Set[14, 15]] = 1
86
+
87
+ assert_equal(
88
+ [[1, Set[11, 12]], [2, Set[12, 13]], [1, Set[13, 14]], [1, Set[14, 15]]],
89
+ @ssm.get(Set[11, 12, 13, 14, 15]))
90
+ end
91
+ end
@@ -66,6 +66,24 @@ class UtilTest < Test::Unit::TestCase
66
66
  merge_adjacent_strings(["foo ", "bar ", "baz", :bang, "biz", " bop", 12]))
67
67
  end
68
68
 
69
+ def test_intersperse
70
+ assert_equal(["foo", " ", "bar", " ", "baz"],
71
+ intersperse(%w[foo bar baz], " "))
72
+ assert_equal([], intersperse([], " "))
73
+ end
74
+
75
+ def test_substitute
76
+ assert_equal(["foo", "bar", "baz", 3, 4],
77
+ substitute([1, 2, 3, 4], [1, 2], ["foo", "bar", "baz"]))
78
+ assert_equal([1, "foo", "bar", "baz", 4],
79
+ substitute([1, 2, 3, 4], [2, 3], ["foo", "bar", "baz"]))
80
+ assert_equal([1, 2, "foo", "bar", "baz"],
81
+ substitute([1, 2, 3, 4], [3, 4], ["foo", "bar", "baz"]))
82
+
83
+ assert_equal([1, "foo", "bar", "baz", 2, 3, 4],
84
+ substitute([1, 2, 2, 2, 3, 4], [2, 2], ["foo", "bar", "baz"]))
85
+ end
86
+
69
87
  def test_strip_string_array
70
88
  assert_equal(["foo ", " bar ", " baz"],
71
89
  strip_string_array([" foo ", " bar ", " baz "]))
@@ -75,6 +93,13 @@ class UtilTest < Test::Unit::TestCase
75
93
  strip_string_array([" foo ", " bar ", :baz]))
76
94
  end
77
95
 
96
+ def test_paths
97
+ assert_equal([[1, 3, 5], [2, 3, 5], [1, 4, 5], [2, 4, 5]],
98
+ paths([[1, 2], [3, 4], [5]]))
99
+ assert_equal([[]], paths([]))
100
+ assert_equal([[1, 2, 3]], paths([[1], [2], [3]]))
101
+ end
102
+
78
103
  def test_silence_warnings
79
104
  old_stderr, $stderr = $stderr, StringIO.new
80
105
  warn "Out"
@@ -183,7 +183,7 @@ SASS
183
183
  def test_multiline_properties
184
184
  assert_scss_to_sass <<SASS, <<SCSS
185
185
  foo bar
186
- baz: bip bam boon
186
+ baz: bip bam boon
187
187
  SASS
188
188
  foo bar {
189
189
  baz:
@@ -194,7 +194,7 @@ SCSS
194
194
 
195
195
  assert_scss_to_scss <<OUT, <<IN
196
196
  foo bar {
197
- baz: bip bam boon; }
197
+ baz: bip bam boon; }
198
198
  OUT
199
199
  foo bar {
200
200
  baz:
@@ -915,7 +915,7 @@ SCSS
915
915
  assert_selector_renders['> E']
916
916
  assert_selector_renders['+ E']
917
917
  assert_selector_renders['~ E']
918
- assert_selector_renders['>> E']
918
+ assert_selector_renders['> > E']
919
919
 
920
920
  assert_selector_renders['E*']
921
921
  assert_selector_renders['E*.foo']
@@ -1031,6 +1031,26 @@ div
1031
1031
  SASS
1032
1032
  end
1033
1033
 
1034
+ def test_sass2_var_in_property_interpolation
1035
+ assert_sass_to_scss <<SCSS, <<SASS
1036
+ foo {
1037
+ a: b \#{$c} d; }
1038
+ SCSS
1039
+ foo
1040
+ a: b \#{!c} d
1041
+ SASS
1042
+ end
1043
+
1044
+ def test_sass2_var_in_selector_interpolation
1045
+ assert_sass_to_scss <<SCSS, <<SASS
1046
+ foo-\#{$c} {
1047
+ a: b; }
1048
+ SCSS
1049
+ foo-\#{!c}
1050
+ a: b
1051
+ SASS
1052
+ end
1053
+
1034
1054
  private
1035
1055
 
1036
1056
  def assert_sass_to_sass(sass, options = {})
@@ -592,6 +592,36 @@ END
592
592
  assert_equal("@a{b:c;#d{e:f}g:h}\n", render(to_render, :style => :compressed))
593
593
  end
594
594
 
595
+ def test_property_hacks
596
+ assert_equal(<<CSS, render(<<SASS))
597
+ foo {
598
+ _name: val;
599
+ *name: val;
600
+ #name: val;
601
+ .name: val;
602
+ name: val; }
603
+ CSS
604
+ foo
605
+ _name: val
606
+ *name: val
607
+ #name: val
608
+ .name: val
609
+ name: val
610
+ SASS
611
+ end
612
+
613
+ def test_properties_with_space_after_colon
614
+ assert_equal <<CSS, render(<<SASS)
615
+ foo {
616
+ bar: baz;
617
+ bizz: bap; }
618
+ CSS
619
+ foo
620
+ bar : baz
621
+ bizz : bap
622
+ SASS
623
+ end
624
+
595
625
  def test_line_annotations
596
626
  assert_equal(<<CSS, render(<<SASS, :line_comments => true, :style => :compact))
597
627
  /* line 2, test_line_annotations_inline.sass */
@@ -980,6 +1010,19 @@ a-\#{$a}
980
1010
  SASS
981
1011
  end
982
1012
 
1013
+ def test_complex_property_interpolation
1014
+ assert_equal(<<CSS, render(<<SASS))
1015
+ a-1 {
1016
+ b-2 3-fizzap18: c-3; }
1017
+ CSS
1018
+ $a: 1
1019
+ $b: 2
1020
+ $c: 3
1021
+ a-\#{$a}
1022
+ b-\#{$b $c}-\#{fizzap + ($c + 15)}: c-\#{$a + $b}
1023
+ SASS
1024
+ end
1025
+
983
1026
  def test_if_directive
984
1027
  assert_equal("a {\n b: 1; }\n", render(<<SASS))
985
1028
  $var: true
@@ -994,16 +1037,16 @@ SASS
994
1037
  def test_for
995
1038
  assert_equal(<<CSS, render(<<SASS))
996
1039
  a-0 {
997
- 2i: 0; }
1040
+ two-i: 0; }
998
1041
 
999
1042
  a-1 {
1000
- 2i: 2; }
1043
+ two-i: 2; }
1001
1044
 
1002
1045
  a-2 {
1003
- 2i: 4; }
1046
+ two-i: 4; }
1004
1047
 
1005
1048
  a-3 {
1006
- 2i: 6; }
1049
+ two-i: 6; }
1007
1050
 
1008
1051
  b-1 {
1009
1052
  j-1: 0; }
@@ -1020,7 +1063,7 @@ CSS
1020
1063
  $a: 3
1021
1064
  @for $i from 0 to $a + 1
1022
1065
  a-\#{$i}
1023
- 2i: 2 * $i
1066
+ two-i: 2 * $i
1024
1067
 
1025
1068
  @for $j from 1 through 4
1026
1069
  b-\#{$j}
@@ -1348,7 +1391,7 @@ SASS
1348
1391
 
1349
1392
  def test_attribute_selector_with_spaces
1350
1393
  assert_equal(<<CSS, render(<<SASS))
1351
- a b[foo = bar] {
1394
+ a b[foo=bar] {
1352
1395
  c: d; }
1353
1396
  CSS
1354
1397
  a
@@ -1542,7 +1585,7 @@ SASS
1542
1585
 
1543
1586
  def test_interpolation_doesnt_deep_unquote_strings
1544
1587
  assert_equal(<<CSS, render(<<SASS))
1545
- .foo-"bar" "baz" {
1588
+ .foo- "bar" "baz" {
1546
1589
  a: b; }
1547
1590
  CSS
1548
1591
  .foo-\#{"bar" "baz"}
@@ -0,0 +1,1045 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../test_helper'
3
+
4
+ class ExtendTest < Test::Unit::TestCase
5
+ def test_basic
6
+ assert_equal <<CSS, render(<<SCSS)
7
+ .foo, .bar {
8
+ a: b; }
9
+ CSS
10
+ .foo {a: b}
11
+ .bar {@extend .foo}
12
+ SCSS
13
+
14
+ assert_equal <<CSS, render(<<SCSS)
15
+ .foo, .bar {
16
+ a: b; }
17
+ CSS
18
+ .bar {@extend .foo}
19
+ .foo {a: b}
20
+ SCSS
21
+
22
+ assert_equal <<CSS, render(<<SCSS)
23
+ .foo, .bar {
24
+ a: b; }
25
+
26
+ .bar {
27
+ c: d; }
28
+ CSS
29
+ .foo {a: b}
30
+ .bar {c: d; @extend .foo}
31
+ SCSS
32
+
33
+ assert_equal <<CSS, render(<<SCSS)
34
+ .foo, .bar {
35
+ a: b; }
36
+
37
+ .bar {
38
+ c: d; }
39
+ CSS
40
+ .foo {a: b}
41
+ .bar {@extend .foo; c: d}
42
+ SCSS
43
+ end
44
+
45
+ def test_indented_syntax
46
+ assert_equal <<CSS, render(<<SASS, :syntax => :sass)
47
+ .foo, .bar {
48
+ a: b; }
49
+ CSS
50
+ .foo
51
+ a: b
52
+ .bar
53
+ @extend .foo
54
+ SASS
55
+
56
+ assert_equal <<CSS, render(<<SASS, :syntax => :sass)
57
+ .foo, .bar {
58
+ a: b; }
59
+ CSS
60
+ .foo
61
+ a: b
62
+ .bar
63
+ @extend \#{".foo"}
64
+ SASS
65
+ end
66
+
67
+ def test_multiple_targets
68
+ assert_equal <<CSS, render(<<SCSS)
69
+ .foo, .bar {
70
+ a: b; }
71
+
72
+ .blip .foo, .blip .bar {
73
+ c: d; }
74
+ CSS
75
+ .foo {a: b}
76
+ .bar {@extend .foo}
77
+ .blip .foo {c: d}
78
+ SCSS
79
+ end
80
+
81
+ def test_multiple_extendees
82
+ assert_equal <<CSS, render(<<SCSS)
83
+ .foo, .baz {
84
+ a: b; }
85
+
86
+ .bar, .baz {
87
+ c: d; }
88
+ CSS
89
+ .foo {a: b}
90
+ .bar {c: d}
91
+ .baz {@extend .foo; @extend .bar}
92
+ SCSS
93
+ end
94
+
95
+ def test_multiple_extends_with_single_extender_and_single_target
96
+ assert_equal <<CSS, render(<<SCSS)
97
+ .foo .bar, .baz .bar, .foo .baz, .baz .baz {
98
+ a: b; }
99
+ CSS
100
+ .foo .bar {a: b}
101
+ .baz {@extend .foo; @extend .bar}
102
+ SCSS
103
+
104
+ assert_equal <<CSS, render(<<SCSS)
105
+ .foo.bar, .bar.baz, .foo.baz, .baz {
106
+ a: b; }
107
+ CSS
108
+ .foo.bar {a: b}
109
+ .baz {@extend .foo; @extend .bar}
110
+ SCSS
111
+ end
112
+
113
+ def test_multiple_extends_with_multiple_extenders_and_single_target
114
+ assert_equal <<CSS, render(<<SCSS)
115
+ .foo .bar, .baz .bar, .foo .bang, .baz .bang {
116
+ a: b; }
117
+ CSS
118
+ .foo .bar {a: b}
119
+ .baz {@extend .foo}
120
+ .bang {@extend .bar}
121
+ SCSS
122
+
123
+ assert_equal <<CSS, render(<<SCSS)
124
+ .foo.bar, .bar.baz, .foo.bang, .baz.bang {
125
+ a: b; }
126
+ CSS
127
+ .foo.bar {a: b}
128
+ .baz {@extend .foo}
129
+ .bang {@extend .bar}
130
+ SCSS
131
+ end
132
+
133
+ def test_chained_extends
134
+ assert_equal <<CSS, render(<<SCSS)
135
+ .foo, .bar, .baz, .bip {
136
+ a: b; }
137
+ CSS
138
+ .foo {a: b}
139
+ .bar {@extend .foo}
140
+ .baz {@extend .bar}
141
+ .bip {@extend .bar}
142
+ SCSS
143
+ end
144
+
145
+ def test_dynamic_extendee
146
+ assert_equal <<CSS, render(<<SCSS)
147
+ .foo, .bar {
148
+ a: b; }
149
+ CSS
150
+ .foo {a: b}
151
+ .bar {@extend \#{".foo"}}
152
+ SCSS
153
+
154
+ assert_equal <<CSS, render(<<SCSS)
155
+ [baz^="blip12px"], .bar {
156
+ a: b; }
157
+ CSS
158
+ [baz^="blip12px"] {a: b}
159
+ .bar {@extend [baz^="blip\#{12px}"]}
160
+ SCSS
161
+ end
162
+
163
+ def test_nested_target
164
+ assert_equal <<CSS, render(<<SCSS)
165
+ .foo .bar, .foo .baz {
166
+ a: b; }
167
+ CSS
168
+ .foo .bar {a: b}
169
+ .baz {@extend .bar}
170
+ SCSS
171
+ end
172
+
173
+ def test_target_with_child
174
+ assert_equal <<CSS, render(<<SCSS)
175
+ .foo .bar, .baz .bar {
176
+ a: b; }
177
+ CSS
178
+ .foo .bar {a: b}
179
+ .baz {@extend .foo}
180
+ SCSS
181
+ end
182
+
183
+ def test_class_unification
184
+ assert_equal <<CSS, render(<<SCSS)
185
+ .foo.bar, .bar.baz {
186
+ a: b; }
187
+ CSS
188
+ .foo.bar {a: b}
189
+ .baz {@extend .foo}
190
+ SCSS
191
+
192
+ assert_equal <<CSS, render(<<SCSS)
193
+ .foo.baz, .baz {
194
+ a: b; }
195
+ CSS
196
+ .foo.baz {a: b}
197
+ .baz {@extend .foo}
198
+ SCSS
199
+ end
200
+
201
+ def test_id_unification
202
+ assert_equal <<CSS, render(<<SCSS)
203
+ .foo.bar, .bar#baz {
204
+ a: b; }
205
+ CSS
206
+ .foo.bar {a: b}
207
+ #baz {@extend .foo}
208
+ SCSS
209
+
210
+ assert_equal <<CSS, render(<<SCSS)
211
+ .foo#baz, #baz {
212
+ a: b; }
213
+ CSS
214
+ .foo#baz {a: b}
215
+ #baz {@extend .foo}
216
+ SCSS
217
+
218
+ assert_equal <<CSS, render(<<SCSS)
219
+ .foo#baz {
220
+ a: b; }
221
+ CSS
222
+ .foo#baz {a: b}
223
+ #bar {@extend .foo}
224
+ SCSS
225
+ end
226
+
227
+ def test_universal_unification_with_simple_target
228
+ assert_equal <<CSS, render(<<SCSS)
229
+ .foo, * {
230
+ a: b; }
231
+ CSS
232
+ .foo {a: b}
233
+ * {@extend .foo}
234
+ SCSS
235
+
236
+ assert_equal <<CSS, render(<<SCSS)
237
+ .foo, *|* {
238
+ a: b; }
239
+ CSS
240
+ .foo {a: b}
241
+ *|* {@extend .foo}
242
+ SCSS
243
+
244
+ assert_equal <<CSS, render(<<SCSS)
245
+ .foo.bar, .bar {
246
+ a: b; }
247
+ CSS
248
+ .foo.bar {a: b}
249
+ * {@extend .foo}
250
+ SCSS
251
+
252
+ assert_equal <<CSS, render(<<SCSS)
253
+ .foo.bar, .bar {
254
+ a: b; }
255
+ CSS
256
+ .foo.bar {a: b}
257
+ *|* {@extend .foo}
258
+ SCSS
259
+
260
+ assert_equal <<CSS, render(<<SCSS)
261
+ .foo.bar, ns|*.bar {
262
+ a: b; }
263
+ CSS
264
+ .foo.bar {a: b}
265
+ ns|* {@extend .foo}
266
+ SCSS
267
+ end
268
+
269
+ def test_universal_unification_with_namespaceless_universal_target
270
+ assert_equal <<CSS, render(<<SCSS)
271
+ *.foo, * {
272
+ a: b; }
273
+ CSS
274
+ *.foo {a: b}
275
+ * {@extend .foo}
276
+ SCSS
277
+
278
+ assert_equal <<CSS, render(<<SCSS)
279
+ *.foo, * {
280
+ a: b; }
281
+ CSS
282
+ *.foo {a: b}
283
+ *|* {@extend .foo}
284
+ SCSS
285
+
286
+ assert_equal <<CSS, render(<<SCSS)
287
+ *|*.foo, * {
288
+ a: b; }
289
+ CSS
290
+ *|*.foo {a: b}
291
+ * {@extend .foo}
292
+ SCSS
293
+
294
+ assert_equal <<CSS, render(<<SCSS)
295
+ *|*.foo, *|* {
296
+ a: b; }
297
+ CSS
298
+ *|*.foo {a: b}
299
+ *|* {@extend .foo}
300
+ SCSS
301
+
302
+ assert_equal <<CSS, render(<<SCSS)
303
+ *.foo, ns|* {
304
+ a: b; }
305
+ CSS
306
+ *.foo {a: b}
307
+ ns|* {@extend .foo}
308
+ SCSS
309
+
310
+ assert_equal <<CSS, render(<<SCSS)
311
+ *|*.foo, ns|* {
312
+ a: b; }
313
+ CSS
314
+ *|*.foo {a: b}
315
+ ns|* {@extend .foo}
316
+ SCSS
317
+ end
318
+
319
+ def test_universal_unification_with_namespaced_universal_target
320
+ assert_equal <<CSS, render(<<SCSS)
321
+ ns|*.foo, ns|* {
322
+ a: b; }
323
+ CSS
324
+ ns|*.foo {a: b}
325
+ * {@extend .foo}
326
+ SCSS
327
+
328
+ assert_equal <<CSS, render(<<SCSS)
329
+ ns|*.foo, ns|* {
330
+ a: b; }
331
+ CSS
332
+ ns|*.foo {a: b}
333
+ *|* {@extend .foo}
334
+ SCSS
335
+
336
+ assert_equal <<CSS, render(<<SCSS)
337
+ ns1|*.foo {
338
+ a: b; }
339
+ CSS
340
+ ns1|*.foo {a: b}
341
+ ns2|* {@extend .foo}
342
+ SCSS
343
+
344
+ assert_equal <<CSS, render(<<SCSS)
345
+ ns|*.foo, ns|* {
346
+ a: b; }
347
+ CSS
348
+ ns|*.foo {a: b}
349
+ ns|* {@extend .foo}
350
+ SCSS
351
+ end
352
+
353
+ def test_universal_unification_with_namespaceless_element_target
354
+ assert_equal <<CSS, render(<<SCSS)
355
+ a.foo, a {
356
+ a: b; }
357
+ CSS
358
+ a.foo {a: b}
359
+ * {@extend .foo}
360
+ SCSS
361
+
362
+ assert_equal <<CSS, render(<<SCSS)
363
+ a.foo, a {
364
+ a: b; }
365
+ CSS
366
+ a.foo {a: b}
367
+ *|* {@extend .foo}
368
+ SCSS
369
+
370
+ assert_equal <<CSS, render(<<SCSS)
371
+ *|a.foo, a {
372
+ a: b; }
373
+ CSS
374
+ *|a.foo {a: b}
375
+ * {@extend .foo}
376
+ SCSS
377
+
378
+ assert_equal <<CSS, render(<<SCSS)
379
+ *|a.foo, *|a {
380
+ a: b; }
381
+ CSS
382
+ *|a.foo {a: b}
383
+ *|* {@extend .foo}
384
+ SCSS
385
+
386
+ assert_equal <<CSS, render(<<SCSS)
387
+ a.foo, ns|a {
388
+ a: b; }
389
+ CSS
390
+ a.foo {a: b}
391
+ ns|* {@extend .foo}
392
+ SCSS
393
+
394
+ assert_equal <<CSS, render(<<SCSS)
395
+ *|a.foo, ns|a {
396
+ a: b; }
397
+ CSS
398
+ *|a.foo {a: b}
399
+ ns|* {@extend .foo}
400
+ SCSS
401
+ end
402
+
403
+ def test_universal_unification_with_namespaced_element_target
404
+ assert_equal <<CSS, render(<<SCSS)
405
+ ns|a.foo, ns|a {
406
+ a: b; }
407
+ CSS
408
+ ns|a.foo {a: b}
409
+ * {@extend .foo}
410
+ SCSS
411
+
412
+ assert_equal <<CSS, render(<<SCSS)
413
+ ns|a.foo, ns|a {
414
+ a: b; }
415
+ CSS
416
+ ns|a.foo {a: b}
417
+ *|* {@extend .foo}
418
+ SCSS
419
+
420
+ assert_equal <<CSS, render(<<SCSS)
421
+ ns1|a.foo {
422
+ a: b; }
423
+ CSS
424
+ ns1|a.foo {a: b}
425
+ ns2|* {@extend .foo}
426
+ SCSS
427
+
428
+ assert_equal <<CSS, render(<<SCSS)
429
+ ns|a.foo, ns|a {
430
+ a: b; }
431
+ CSS
432
+ ns|a.foo {a: b}
433
+ ns|* {@extend .foo}
434
+ SCSS
435
+ end
436
+
437
+ def test_element_unification_with_simple_target
438
+ assert_equal <<CSS, render(<<SCSS)
439
+ .foo, a {
440
+ a: b; }
441
+ CSS
442
+ .foo {a: b}
443
+ a {@extend .foo}
444
+ SCSS
445
+
446
+ assert_equal <<CSS, render(<<SCSS)
447
+ .foo.bar, a.bar {
448
+ a: b; }
449
+ CSS
450
+ .foo.bar {a: b}
451
+ a {@extend .foo}
452
+ SCSS
453
+
454
+ assert_equal <<CSS, render(<<SCSS)
455
+ .foo.bar, *|a.bar {
456
+ a: b; }
457
+ CSS
458
+ .foo.bar {a: b}
459
+ *|a {@extend .foo}
460
+ SCSS
461
+
462
+ assert_equal <<CSS, render(<<SCSS)
463
+ .foo.bar, ns|a.bar {
464
+ a: b; }
465
+ CSS
466
+ .foo.bar {a: b}
467
+ ns|a {@extend .foo}
468
+ SCSS
469
+ end
470
+
471
+ def test_element_unification_with_namespaceless_universal_target
472
+ assert_equal <<CSS, render(<<SCSS)
473
+ *.foo, a {
474
+ a: b; }
475
+ CSS
476
+ *.foo {a: b}
477
+ a {@extend .foo}
478
+ SCSS
479
+
480
+ assert_equal <<CSS, render(<<SCSS)
481
+ *.foo, a {
482
+ a: b; }
483
+ CSS
484
+ *.foo {a: b}
485
+ *|a {@extend .foo}
486
+ SCSS
487
+
488
+ assert_equal <<CSS, render(<<SCSS)
489
+ *|*.foo, a {
490
+ a: b; }
491
+ CSS
492
+ *|*.foo {a: b}
493
+ a {@extend .foo}
494
+ SCSS
495
+
496
+ assert_equal <<CSS, render(<<SCSS)
497
+ *|*.foo, *|a {
498
+ a: b; }
499
+ CSS
500
+ *|*.foo {a: b}
501
+ *|a {@extend .foo}
502
+ SCSS
503
+
504
+ assert_equal <<CSS, render(<<SCSS)
505
+ *.foo, ns|a {
506
+ a: b; }
507
+ CSS
508
+ *.foo {a: b}
509
+ ns|a {@extend .foo}
510
+ SCSS
511
+
512
+ assert_equal <<CSS, render(<<SCSS)
513
+ *|*.foo, ns|a {
514
+ a: b; }
515
+ CSS
516
+ *|*.foo {a: b}
517
+ ns|a {@extend .foo}
518
+ SCSS
519
+ end
520
+
521
+ def test_element_unification_with_namespaced_universal_target
522
+ assert_equal <<CSS, render(<<SCSS)
523
+ ns|*.foo, ns|a {
524
+ a: b; }
525
+ CSS
526
+ ns|*.foo {a: b}
527
+ a {@extend .foo}
528
+ SCSS
529
+
530
+ assert_equal <<CSS, render(<<SCSS)
531
+ ns|*.foo, ns|a {
532
+ a: b; }
533
+ CSS
534
+ ns|*.foo {a: b}
535
+ *|a {@extend .foo}
536
+ SCSS
537
+
538
+ assert_equal <<CSS, render(<<SCSS)
539
+ ns1|*.foo {
540
+ a: b; }
541
+ CSS
542
+ ns1|*.foo {a: b}
543
+ ns2|a {@extend .foo}
544
+ SCSS
545
+
546
+ assert_equal <<CSS, render(<<SCSS)
547
+ ns|*.foo, ns|a {
548
+ a: b; }
549
+ CSS
550
+ ns|*.foo {a: b}
551
+ ns|a {@extend .foo}
552
+ SCSS
553
+ end
554
+
555
+ def test_element_unification_with_namespaceless_element_target
556
+ assert_equal <<CSS, render(<<SCSS)
557
+ a.foo, a {
558
+ a: b; }
559
+ CSS
560
+ a.foo {a: b}
561
+ a {@extend .foo}
562
+ SCSS
563
+
564
+ assert_equal <<CSS, render(<<SCSS)
565
+ a.foo, a {
566
+ a: b; }
567
+ CSS
568
+ a.foo {a: b}
569
+ *|a {@extend .foo}
570
+ SCSS
571
+
572
+ assert_equal <<CSS, render(<<SCSS)
573
+ *|a.foo, a {
574
+ a: b; }
575
+ CSS
576
+ *|a.foo {a: b}
577
+ a {@extend .foo}
578
+ SCSS
579
+
580
+ assert_equal <<CSS, render(<<SCSS)
581
+ *|a.foo, *|a {
582
+ a: b; }
583
+ CSS
584
+ *|a.foo {a: b}
585
+ *|a {@extend .foo}
586
+ SCSS
587
+
588
+ assert_equal <<CSS, render(<<SCSS)
589
+ a.foo, ns|a {
590
+ a: b; }
591
+ CSS
592
+ a.foo {a: b}
593
+ ns|a {@extend .foo}
594
+ SCSS
595
+
596
+ assert_equal <<CSS, render(<<SCSS)
597
+ *|a.foo, ns|a {
598
+ a: b; }
599
+ CSS
600
+ *|a.foo {a: b}
601
+ ns|a {@extend .foo}
602
+ SCSS
603
+
604
+ assert_equal <<CSS, render(<<SCSS)
605
+ a.foo {
606
+ a: b; }
607
+ CSS
608
+ a.foo {a: b}
609
+ h1 {@extend .foo}
610
+ SCSS
611
+ end
612
+
613
+ def test_element_unification_with_namespaced_element_target
614
+ assert_equal <<CSS, render(<<SCSS)
615
+ ns|a.foo, ns|a {
616
+ a: b; }
617
+ CSS
618
+ ns|a.foo {a: b}
619
+ a {@extend .foo}
620
+ SCSS
621
+
622
+ assert_equal <<CSS, render(<<SCSS)
623
+ ns|a.foo, ns|a {
624
+ a: b; }
625
+ CSS
626
+ ns|a.foo {a: b}
627
+ *|a {@extend .foo}
628
+ SCSS
629
+
630
+ assert_equal <<CSS, render(<<SCSS)
631
+ ns1|a.foo {
632
+ a: b; }
633
+ CSS
634
+ ns1|a.foo {a: b}
635
+ ns2|a {@extend .foo}
636
+ SCSS
637
+
638
+ assert_equal <<CSS, render(<<SCSS)
639
+ ns|a.foo, ns|a {
640
+ a: b; }
641
+ CSS
642
+ ns|a.foo {a: b}
643
+ ns|a {@extend .foo}
644
+ SCSS
645
+ end
646
+
647
+ def test_attribute_unification
648
+ assert_equal <<CSS, render(<<SCSS)
649
+ [foo=bar].baz, [foo=bar][foo=baz] {
650
+ a: b; }
651
+ CSS
652
+ [foo=bar].baz {a: b}
653
+ [foo=baz] {@extend .baz}
654
+ SCSS
655
+
656
+ assert_equal <<CSS, render(<<SCSS)
657
+ [foo=bar].baz, [foo=bar][foo^=bar] {
658
+ a: b; }
659
+ CSS
660
+ [foo=bar].baz {a: b}
661
+ [foo^=bar] {@extend .baz}
662
+ SCSS
663
+
664
+ assert_equal <<CSS, render(<<SCSS)
665
+ [foo=bar].baz, [foo=bar][foot=bar] {
666
+ a: b; }
667
+ CSS
668
+ [foo=bar].baz {a: b}
669
+ [foot=bar] {@extend .baz}
670
+ SCSS
671
+
672
+ assert_equal <<CSS, render(<<SCSS)
673
+ [foo=bar].baz, [foo=bar][ns|foo=bar] {
674
+ a: b; }
675
+ CSS
676
+ [foo=bar].baz {a: b}
677
+ [ns|foo=bar] {@extend .baz}
678
+ SCSS
679
+
680
+ assert_equal <<CSS, render(<<SCSS)
681
+ [foo=bar].baz, [foo=bar] {
682
+ a: b; }
683
+ CSS
684
+ [foo=bar].baz {a: b}
685
+ [foo=bar] {@extend .baz}
686
+ SCSS
687
+ end
688
+
689
+ def test_pseudo_unification
690
+ assert_equal <<CSS, render(<<SCSS)
691
+ :foo.baz, :foo:foo(2n+1) {
692
+ a: b; }
693
+ CSS
694
+ :foo.baz {a: b}
695
+ :foo(2n+1) {@extend .baz}
696
+ SCSS
697
+
698
+ assert_equal <<CSS, render(<<SCSS)
699
+ :foo.baz, :foo::foo {
700
+ a: b; }
701
+ CSS
702
+ :foo.baz {a: b}
703
+ ::foo {@extend .baz}
704
+ SCSS
705
+
706
+ assert_equal <<CSS, render(<<SCSS)
707
+ ::foo.baz {
708
+ a: b; }
709
+ CSS
710
+ ::foo.baz {a: b}
711
+ ::bar {@extend .baz}
712
+ SCSS
713
+
714
+ assert_equal <<CSS, render(<<SCSS)
715
+ ::foo.baz {
716
+ a: b; }
717
+ CSS
718
+ ::foo.baz {a: b}
719
+ ::foo(2n+1) {@extend .baz}
720
+ SCSS
721
+
722
+ assert_equal <<CSS, render(<<SCSS)
723
+ ::foo.baz, ::foo {
724
+ a: b; }
725
+ CSS
726
+ ::foo.baz {a: b}
727
+ ::foo {@extend .baz}
728
+ SCSS
729
+
730
+ assert_equal <<CSS, render(<<SCSS)
731
+ ::foo(2n+1).baz, ::foo(2n+1) {
732
+ a: b; }
733
+ CSS
734
+ ::foo(2n+1).baz {a: b}
735
+ ::foo(2n+1) {@extend .baz}
736
+ SCSS
737
+
738
+ assert_equal <<CSS, render(<<SCSS)
739
+ :foo.baz, :foo:bar {
740
+ a: b; }
741
+ CSS
742
+ :foo.baz {a: b}
743
+ :bar {@extend .baz}
744
+ SCSS
745
+
746
+ assert_equal <<CSS, render(<<SCSS)
747
+ :foo.baz, :foo {
748
+ a: b; }
749
+ CSS
750
+ :foo.baz {a: b}
751
+ :foo {@extend .baz}
752
+ SCSS
753
+ end
754
+
755
+ def test_pseudoelement_remains_at_end_of_selector
756
+ assert_equal <<CSS, render(<<SCSS)
757
+ .foo::bar, .baz::bar {
758
+ a: b; }
759
+ CSS
760
+ .foo::bar {a: b}
761
+ .baz {@extend .foo}
762
+ SCSS
763
+
764
+ assert_equal <<CSS, render(<<SCSS)
765
+ a.foo::bar, a.baz::bar {
766
+ a: b; }
767
+ CSS
768
+ a.foo::bar {a: b}
769
+ .baz {@extend .foo}
770
+ SCSS
771
+ end
772
+
773
+ def test_negation_unification
774
+ assert_equal <<CSS, render(<<SCSS)
775
+ :not(.foo).baz, :not(.foo):not(.bar) {
776
+ a: b; }
777
+ CSS
778
+ :not(.foo).baz {a: b}
779
+ :not(.bar) {@extend .baz}
780
+ SCSS
781
+
782
+ assert_equal <<CSS, render(<<SCSS)
783
+ :not(.foo).baz, :not(.foo) {
784
+ a: b; }
785
+ CSS
786
+ :not(.foo).baz {a: b}
787
+ :not(.foo) {@extend .baz}
788
+ SCSS
789
+
790
+ assert_equal <<CSS, render(<<SCSS)
791
+ :not([a=b]).baz, :not([a=b]) {
792
+ a: b; }
793
+ CSS
794
+ :not([a=b]).baz {a: b}
795
+ :not([a = b]) {@extend .baz}
796
+ SCSS
797
+ end
798
+
799
+ ## Long Extendees
800
+
801
+ def test_long_extendee
802
+ assert_equal <<CSS, render(<<SCSS)
803
+ .foo.bar, .baz {
804
+ a: b; }
805
+ CSS
806
+ .foo.bar {a: b}
807
+ .baz {@extend .foo.bar}
808
+ SCSS
809
+ end
810
+
811
+ def test_long_extendee_requires_all_selectors
812
+ assert_equal <<CSS, render(<<SCSS)
813
+ .foo {
814
+ a: b; }
815
+ CSS
816
+ .foo {a: b}
817
+ .baz {@extend .foo.bar}
818
+ SCSS
819
+ end
820
+
821
+ def test_long_extendee_matches_supersets
822
+ assert_equal <<CSS, render(<<SCSS)
823
+ .foo.bar.bap, .bap.baz {
824
+ a: b; }
825
+ CSS
826
+ .foo.bar.bap {a: b}
827
+ .baz {@extend .foo.bar}
828
+ SCSS
829
+ end
830
+
831
+ def test_long_extendee_runs_unification
832
+ assert_equal <<CSS, render(<<SCSS)
833
+ ns|*.foo.bar, ns|a.baz {
834
+ a: b; }
835
+ CSS
836
+ ns|*.foo.bar {a: b}
837
+ a.baz {@extend .foo.bar}
838
+ SCSS
839
+ end
840
+
841
+ ## Long Extenders
842
+
843
+ def test_long_extender
844
+ assert_equal <<CSS, render(<<SCSS)
845
+ .foo.bar, .bar.baz.bang {
846
+ a: b; }
847
+ CSS
848
+ .foo.bar {a: b}
849
+ .baz.bang {@extend .foo}
850
+ SCSS
851
+ end
852
+
853
+ def test_long_extender_runs_unification
854
+ assert_equal <<CSS, render(<<SCSS)
855
+ ns|*.foo.bar, ns|a.bar.baz {
856
+ a: b; }
857
+ CSS
858
+ ns|*.foo.bar {a: b}
859
+ a.baz {@extend .foo}
860
+ SCSS
861
+ end
862
+
863
+ def test_long_extender_aborts_unification
864
+ assert_equal <<CSS, render(<<SCSS)
865
+ a.foo#bar {
866
+ a: b; }
867
+ CSS
868
+ a.foo#bar {a: b}
869
+ h1.baz {@extend .foo}
870
+ SCSS
871
+
872
+ assert_equal <<CSS, render(<<SCSS)
873
+ a.foo#bar {
874
+ a: b; }
875
+ CSS
876
+ a.foo#bar {a: b}
877
+ .bang#baz {@extend .foo}
878
+ SCSS
879
+ end
880
+
881
+ ## Nested Extenders
882
+
883
+ def test_nested_extender
884
+ assert_equal <<CSS, render(<<SCSS)
885
+ .foo, foo bar {
886
+ a: b; }
887
+ CSS
888
+ .foo {a: b}
889
+ foo bar {@extend .foo}
890
+ SCSS
891
+ end
892
+
893
+ def test_nested_extender_runs_unification
894
+ assert_equal <<CSS, render(<<SCSS)
895
+ .foo.bar, foo bar.bar {
896
+ a: b; }
897
+ CSS
898
+ .foo.bar {a: b}
899
+ foo bar {@extend .foo}
900
+ SCSS
901
+ end
902
+
903
+ def test_nested_extender_aborts_unification
904
+ assert_equal <<CSS, render(<<SCSS)
905
+ baz.foo {
906
+ a: b; }
907
+ CSS
908
+ baz.foo {a: b}
909
+ foo bar {@extend .foo}
910
+ SCSS
911
+ end
912
+
913
+ def test_nested_extender_interleaves_parents_with_unification
914
+ assert_equal <<CSS, render(<<SCSS)
915
+ .baz .foo, .baz foo bar, foo.baz bar, foo .baz bar {
916
+ a: b; }
917
+ CSS
918
+ .baz .foo {a: b}
919
+ foo bar {@extend .foo}
920
+ SCSS
921
+ end
922
+
923
+ def test_nested_extender_interleaves_parents_with_aborted_unification
924
+ assert_equal <<CSS, render(<<SCSS)
925
+ baz .foo, baz foo bar, foo baz bar {
926
+ a: b; }
927
+ CSS
928
+ baz .foo {a: b}
929
+ foo bar {@extend .foo}
930
+ SCSS
931
+ end
932
+
933
+ def test_nested_extender_with_lots_of_interleaving
934
+ # Please, never ever do this in a real stylesheet
935
+ assert_equal <<CSS, render(<<SCSS)
936
+ .foo .bar .baz .bang, .foo .bar .baz .foo2 .bar2 .baz2 .bang2, .foo .bar .foo2.baz .bar2 .baz2 .bang2, .foo .bar .foo2 .baz .bar2 .baz2 .bang2, .foo .bar .foo2 .bar2.baz .baz2 .bang2, .foo .bar .foo2 .bar2 .baz .baz2 .bang2, .foo .bar .foo2 .bar2 .baz2.baz .bang2, .foo .bar .foo2 .bar2 .baz2 .baz .bang2, .foo .foo2.bar .baz .bar2 .baz2 .bang2, .foo .foo2.bar .bar2.baz .baz2 .bang2, .foo .foo2.bar .bar2 .baz .baz2 .bang2, .foo .foo2.bar .bar2 .baz2.baz .bang2, .foo .foo2.bar .bar2 .baz2 .baz .bang2, .foo .foo2 .bar .baz .bar2 .baz2 .bang2, .foo .foo2 .bar .bar2.baz .baz2 .bang2, .foo .foo2 .bar .bar2 .baz .baz2 .bang2, .foo .foo2 .bar .bar2 .baz2.baz .bang2, .foo .foo2 .bar .bar2 .baz2 .baz .bang2, .foo .foo2 .bar2.bar .baz .baz2 .bang2, .foo .foo2 .bar2.bar .baz2.baz .bang2, .foo .foo2 .bar2.bar .baz2 .baz .bang2, .foo .foo2 .bar2 .bar .baz .baz2 .bang2, .foo .foo2 .bar2 .bar .baz2.baz .bang2, .foo .foo2 .bar2 .bar .baz2 .baz .bang2, .foo .foo2 .bar2 .baz2.bar .baz .bang2, .foo .foo2 .bar2 .baz2 .bar .baz .bang2, .foo2.foo .bar .baz .bar2 .baz2 .bang2, .foo2.foo .bar .bar2.baz .baz2 .bang2, .foo2.foo .bar .bar2 .baz .baz2 .bang2, .foo2.foo .bar .bar2 .baz2.baz .bang2, .foo2.foo .bar .bar2 .baz2 .baz .bang2, .foo2.foo .bar2.bar .baz .baz2 .bang2, .foo2.foo .bar2.bar .baz2.baz .bang2, .foo2.foo .bar2.bar .baz2 .baz .bang2, .foo2.foo .bar2 .bar .baz .baz2 .bang2, .foo2.foo .bar2 .bar .baz2.baz .bang2, .foo2.foo .bar2 .bar .baz2 .baz .bang2, .foo2.foo .bar2 .baz2.bar .baz .bang2, .foo2.foo .bar2 .baz2 .bar .baz .bang2, .foo2 .foo .bar .baz .bar2 .baz2 .bang2, .foo2 .foo .bar .bar2.baz .baz2 .bang2, .foo2 .foo .bar .bar2 .baz .baz2 .bang2, .foo2 .foo .bar .bar2 .baz2.baz .bang2, .foo2 .foo .bar .bar2 .baz2 .baz .bang2, .foo2 .foo .bar2.bar .baz .baz2 .bang2, .foo2 .foo .bar2.bar .baz2.baz .bang2, .foo2 .foo .bar2.bar .baz2 .baz .bang2, .foo2 .foo .bar2 .bar .baz .baz2 .bang2, .foo2 .foo .bar2 .bar .baz2.baz .bang2, .foo2 .foo .bar2 .bar .baz2 .baz .bang2, .foo2 .foo .bar2 .baz2.bar .baz .bang2, .foo2 .foo .bar2 .baz2 .bar .baz .bang2, .foo2 .bar2.foo .bar .baz .baz2 .bang2, .foo2 .bar2.foo .bar .baz2.baz .bang2, .foo2 .bar2.foo .bar .baz2 .baz .bang2, .foo2 .bar2.foo .baz2.bar .baz .bang2, .foo2 .bar2.foo .baz2 .bar .baz .bang2, .foo2 .bar2 .foo .bar .baz .baz2 .bang2, .foo2 .bar2 .foo .bar .baz2.baz .bang2, .foo2 .bar2 .foo .bar .baz2 .baz .bang2, .foo2 .bar2 .foo .baz2.bar .baz .bang2, .foo2 .bar2 .foo .baz2 .bar .baz .bang2, .foo2 .bar2 .baz2.foo .bar .baz .bang2, .foo2 .bar2 .baz2 .foo .bar .baz .bang2 {
937
+ a: b; }
938
+ CSS
939
+ .foo .bar .baz .bang {a: b}
940
+ .foo2 .bar2 .baz2 .bang2 {@extend .bang}
941
+ SCSS
942
+ end
943
+
944
+ def test_nested_extender_with_child_selector
945
+ assert_equal <<CSS, render(<<SCSS)
946
+ .baz .foo, .baz foo > bar {
947
+ a: b; }
948
+ CSS
949
+ .baz .foo {a: b}
950
+ foo > bar {@extend .foo}
951
+ SCSS
952
+ end
953
+
954
+ def test_nested_extender_with_descendant_and_child_selector
955
+ assert_equal <<CSS, render(<<SCSS)
956
+ .baz .foo, .baz bang foo > bar, bang.baz foo > bar, bang .baz foo > bar {
957
+ a: b; }
958
+ CSS
959
+ .baz .foo {a: b}
960
+ bang foo > bar {@extend .foo}
961
+ SCSS
962
+ end
963
+
964
+ def test_nested_extender_with_child_selector_unifies
965
+ assert_equal <<CSS, render(<<SCSS)
966
+ .baz.foo, foo > bar.baz {
967
+ a: b; }
968
+ CSS
969
+ .baz.foo {a: b}
970
+ foo > bar {@extend .foo}
971
+ SCSS
972
+ end
973
+
974
+ def test_nested_extender_with_child_selector_and_more
975
+ assert_equal <<CSS, render(<<SCSS)
976
+ .foo .bar, .foo foo > bar baz, foo > bar.foo baz, foo > bar .foo baz {
977
+ a: b; }
978
+ CSS
979
+ .foo .bar {a: b}
980
+ foo > bar baz {@extend .bar}
981
+ SCSS
982
+ end
983
+
984
+ def test_nested_extender_with_trailing_child_selector
985
+ assert_raise(Sass::SyntaxError, "bar > can't extend: invalid selector") do
986
+ render("bar > {@extend .baz}")
987
+ end
988
+ end
989
+
990
+ def test_nested_extender_with_sibling_selector
991
+ assert_equal <<CSS, render(<<SCSS)
992
+ .baz .foo, .baz foo + bar {
993
+ a: b; }
994
+ CSS
995
+ .baz .foo {a: b}
996
+ foo + bar {@extend .foo}
997
+ SCSS
998
+ end
999
+
1000
+ def test_nested_extender_with_hacky_selector
1001
+ assert_equal <<CSS, render(<<SCSS)
1002
+ .baz .foo, .baz foo + > > + bar {
1003
+ a: b; }
1004
+ CSS
1005
+ .baz .foo {a: b}
1006
+ foo + > > + bar {@extend .foo}
1007
+ SCSS
1008
+
1009
+ assert_equal <<CSS, render(<<SCSS)
1010
+ .baz .foo, .baz > > bar {
1011
+ a: b; }
1012
+ CSS
1013
+ .baz .foo {a: b}
1014
+ > > bar {@extend .foo}
1015
+ SCSS
1016
+ end
1017
+
1018
+ def test_nested_extender_merges_with_same_selector
1019
+ assert_equal <<CSS, render(<<SCSS)
1020
+ .foo .bar, .foo .baz {
1021
+ a: b; }
1022
+ CSS
1023
+ .foo {
1024
+ .bar {a: b}
1025
+ .baz {@extend .bar} }
1026
+ SCSS
1027
+ end
1028
+
1029
+ def test_nested_extender_with_child_selector_merges_with_same_selector
1030
+ assert_equal <<CSS, render(<<SCSS)
1031
+ .foo > .bar .baz, .foo > .bar .bang {
1032
+ a: b; }
1033
+ CSS
1034
+ .foo > .bar .baz {a: b}
1035
+ .foo > .bar .bang {@extend .baz}
1036
+ SCSS
1037
+ end
1038
+
1039
+ private
1040
+
1041
+ def render(sass, options = {})
1042
+ munge_filename options
1043
+ Sass::Engine.new(sass, {:syntax => :scss}.merge(options)).render
1044
+ end
1045
+ end