#!/usr/bin/env ruby require File.dirname(__FILE__) + '/../test_helper' class ExtendTest < Test::Unit::TestCase def test_basic assert_equal < :sass) .foo, .bar { a: b; } CSS .foo a: b .bar @extend .foo SASS assert_equal < :sass) .foo, .bar { a: b; } CSS .foo a: b .bar @extend \#{".foo"} SASS end def test_multiple_targets assert_equal < bar { a: b; } CSS .baz .foo {a: b} foo > bar {@extend .foo} SCSS end def test_nested_extender_finds_common_selectors_around_child_selector assert_equal < b c .c1, a > b c .c2 { a: b; } CSS a > b c .c1 {a: b} a c .c2 {@extend .c1} SCSS assert_equal < b c .c1, a > b c .c2 { a: b; } CSS a > b c .c1 {a: b} b c .c2 {@extend .c1} SCSS end def test_nested_extender_doesnt_find_common_selectors_around_adjacent_sibling_selector assert_equal < .bap .foo, .bip > .bap .grip > .bap .bar, .grip > .bap .bip > .bap .bar { a: b; } CSS .bip > .bap .foo {a: b} .grip > .bap .bar {@extend .foo} SCSS assert_equal < .bip .foo, .bap > .bip .bap > .grip .bar, .bap > .grip .bap > .bip .bar { a: b; } CSS .bap > .bip .foo {a: b} .bap > .grip .bar {@extend .foo} SCSS end def test_nested_extender_with_child_selector_unifies assert_equal < bar.baz { a: b; } CSS .baz.foo {a: b} foo > bar {@extend .foo} SCSS assert_equal < .foo, .baz > .bar { a: b; } CSS .baz > { .foo {a: b} .bar {@extend .foo} } SCSS assert_equal < .baz { a: b; } CSS .foo { .bar {a: b} > .baz {@extend .bar} } SCSS assert_equal < .baz { a: b; } CSS .foo { .bar {a: b} .bip > .baz {@extend .bar} } SCSS assert_equal < .baz { a: b; } CSS .foo { .bip .bar {a: b} > .baz {@extend .bar} } SCSS assert_equal < .bar, .foo > .bip + .baz { a: b; } CSS .foo > .bar {a: b} .bip + .baz {@extend .bar} SCSS assert_equal < .foo + .baz { a: b; } CSS .foo + .bar {a: b} .bip > .baz {@extend .bar} SCSS assert_equal < .bar, .bip.foo > .baz { a: b; } CSS .foo > .bar {a: b} .bip > .baz {@extend .bar} SCSS end def test_nested_extender_with_trailing_child_selector assert_raise(Sass::SyntaxError, "bar > can't extend: invalid selector") do render("bar > {@extend .baz}") end end def test_nested_extender_with_sibling_selector assert_equal < > + bar, foo .baz + > > + bar { a: b; } CSS .baz .foo {a: b} foo + > > + bar {@extend .foo} SCSS assert_equal < > .baz bar { a: b; } CSS .baz .foo {a: b} > > bar {@extend .foo} SCSS end def test_nested_extender_merges_with_same_selector assert_equal < .bar .baz, .foo > .bar .bang { a: b; } CSS .foo > .bar .baz {a: b} .foo > .bar .bang {@extend .baz} SCSS end # Combinator Unification def test_combinator_unification_for_hacky_combinators assert_equal < + x, .a .b > + y, .b .a > + y { a: b; } CSS .a > + x {a: b} .b y {@extend x} SCSS assert_equal < + y, .b .a > + y { a: b; } CSS .a x {a: b} .b > + y {@extend x} SCSS assert_equal < + x, .a .b > + y, .b .a > + y { a: b; } CSS .a > + x {a: b} .b > + y {@extend x} SCSS assert_equal < + x, .a .b ~ > + y, .b .a ~ > + y { a: b; } CSS .a ~ > + x {a: b} .b > + y {@extend x} SCSS assert_equal < x { a: b; } CSS .a + > x {a: b} .b > + y {@extend x} SCSS assert_equal < x { a: b; } CSS .a + > x {a: b} .b > + y {@extend x} SCSS assert_equal < + .b > x, .a .c ~ > + .d.b > y, .c .a ~ > + .d.b > y { a: b; } CSS .a ~ > + .b > x {a: b} .c > + .d > y {@extend x} SCSS end def test_combinator_unification_double_tilde assert_equal < x, .a > .b ~ y { a: b; } CSS .a > x {a: b} .b ~ y {@extend x} SCSS assert_equal < x, .a > .b + y { a: b; } CSS .a > x {a: b} .b + y {@extend x} SCSS assert_equal < .a ~ y { a: b; } CSS .a ~ x {a: b} .b > y {@extend x} SCSS assert_equal < .a + y { a: b; } CSS .a + x {a: b} .b > y {@extend x} SCSS end def test_combinator_unification_double_angle assert_equal < x, .b.a > y { a: b; } CSS .a.b > x {a: b} .b > y {@extend x} SCSS assert_equal < x, .a.b > y { a: b; } CSS .a > x {a: b} .a.b > y {@extend x} SCSS assert_equal < x, .b.a > y { a: b; } CSS .a > x {a: b} .b > y {@extend x} SCSS assert_equal < x { a: b; } CSS a.a > x {a: b} b.b > y {@extend x} SCSS end def test_combinator_unification_double_plus assert_equal < x, .a.b > y { a: b; } CSS .a.b > x {a: b} .a y {@extend x} SCSS assert_equal < x, .a.b .a > y { a: b; } CSS .a > x {a: b} .a.b y {@extend x} SCSS assert_equal < x, .b .a > y { a: b; } CSS .a > x {a: b} .b y {@extend x} SCSS assert_equal < y { a: b; } CSS .a.b x {a: b} .a > y {@extend x} SCSS assert_equal < y { a: b; } CSS .a x {a: b} .a.b > y {@extend x} SCSS assert_equal < y { a: b; } CSS .a x {a: b} .b > y {@extend x} SCSS end def test_combinator_unification_plus_space assert_equal < .b + x, .c.a > .d.b + y { a: b; } CSS .a > .b + x {a: b} .c > .d + y {@extend x} SCSS assert_equal < .b + x, .c.a > .b + y { a: b; } CSS .a > .b + x {a: b} .c > y {@extend x} SCSS end def test_combinator_unification_with_newlines assert_equal < .b + x, .c.a > .d.b + y { a: b; } CSS .a > .b + x {a: b} .c > .d + y {@extend x} SCSS end # Loops def test_extend_self_loop assert_equal < .foo, > foo bar { a: b; } CSS > .foo {a: b} foo bar {@extend .foo} SCSS end def test_nested_selector_with_child_selector_hack_extender assert_equal < .foo foo bar, > foo .foo bar { a: b; } CSS .foo .bar {a: b} > foo bar {@extend .bar} SCSS end def test_nested_selector_with_child_selector_hack_extender_and_extendee assert_equal < .foo, > foo bar { a: b; } CSS > .foo {a: b} > foo bar {@extend .foo} SCSS end def test_nested_selector_with_child_selector_hack_extender_and_sibling_selector_extendee assert_equal < foo bar {@extend .foo} SCSS end def test_nested_selector_with_child_selector_hack_extender_and_extendee_and_newline assert_equal < .foo, > flip, > foo bar { a: b; } CSS > .foo {a: b} flip, > foo bar {@extend .foo} SCSS end private def render(sass, options = {}) munge_filename options Sass::Engine.new(sass, {:syntax => :scss}.merge(options)).render end end