#!/usr/bin/env ruby # -*- coding: utf-8 -*- require File.dirname(__FILE__) + '/test_helper' require 'sass/scss/css_parser' # These tests just test the parsing of CSS # (both standard and any hacks we intend to support). # Tests of SCSS-specific behavior go in scss_test.rb. class ScssCssTest < Test::Unit::TestCase include ScssTestHelper def test_basic_scss assert_parses < baz {bar: baz} SCSS end def test_unicode assert_parses < F') assert_selector_parses('E + F') assert_selector_parses('E ~ F') end # Taken from http://www.w3.org/TR/css3-selectors/#selectors, # but without the element names def test_lonely_selectors assert_selector_parses('[foo]') assert_selector_parses('[foo="bar"]') assert_selector_parses('[foo~="bar"]') assert_selector_parses('[foo^="bar"]') assert_selector_parses('[foo$="bar"]') assert_selector_parses('[foo*="bar"]') assert_selector_parses('[foo|="en"]') assert_selector_parses(':root') assert_selector_parses(':nth-child(n)') assert_selector_parses(':nth-last-child(n)') assert_selector_parses(':nth-of-type(n)') assert_selector_parses(':nth-last-of-type(n)') assert_selector_parses(':first-child') assert_selector_parses(':last-child') assert_selector_parses(':first-of-type') assert_selector_parses(':last-of-type') assert_selector_parses(':only-child') assert_selector_parses(':only-of-type') assert_selector_parses(':empty') assert_selector_parses(':link') assert_selector_parses(':visited') assert_selector_parses(':active') assert_selector_parses(':hover') assert_selector_parses(':focus') assert_selector_parses(':target') assert_selector_parses(':lang(fr)') assert_selector_parses(':enabled') assert_selector_parses(':disabled') assert_selector_parses(':checked') assert_selector_parses('::first-line') assert_selector_parses('::first-letter') assert_selector_parses('::before') assert_selector_parses('::after') assert_selector_parses('.warning') assert_selector_parses('#myid') assert_selector_parses(':not(s)') end def test_attribute_selectors_with_identifiers assert_selector_parses('[foo~=bar]') assert_selector_parses('[foo^=bar]') assert_selector_parses('[foo$=bar]') assert_selector_parses('[foo*=bar]') assert_selector_parses('[foo|=en]') end def test_nth_selectors assert_selector_parses(':nth-child(-n)') assert_selector_parses(':nth-child(+n)') assert_selector_parses(':nth-child(even)') assert_selector_parses(':nth-child(odd)') assert_selector_parses(':nth-child(50)') assert_selector_parses(':nth-child(-50)') assert_selector_parses(':nth-child(+50)') assert_selector_parses(':nth-child(2n+3)') assert_selector_parses(':nth-child(2n-3)') assert_selector_parses(':nth-child(+2n-3)') assert_selector_parses(':nth-child(-2n+3)') assert_selector_parses(':nth-child(-2n+ 3)') assert_selector_parses(':nth-child( 2n + 3 )') end def test_negation_selectors assert_selector_parses(':not(foo|bar)') assert_selector_parses(':not(*|bar)') assert_selector_parses(':not(foo|*)') assert_selector_parses(':not(*|*)') assert_selector_parses(':not(#blah)') assert_selector_parses(':not(.blah)') assert_selector_parses(':not([foo])') assert_selector_parses(':not([foo^="bar"])') assert_selector_parses(':not([baz|foo~="bar"])') assert_selector_parses(':not(:hover)') assert_selector_parses(':not(:nth-child(2n + 3))') end def test_namespaced_selectors assert_selector_parses('foo|E') assert_selector_parses('*|E') assert_selector_parses('foo|*') assert_selector_parses('*|*') end def test_namespaced_attribute_selectors assert_selector_parses('[foo|bar=baz]') assert_selector_parses('[*|bar=baz]') assert_selector_parses('[foo|bar|=baz]') end def test_comma_selectors assert_selector_parses('E, F') assert_selector_parses('E F, G H') assert_selector_parses('E > F, G > H') end def test_selectors_with_newlines assert_selector_parses("E,\nF") assert_selector_parses("E\nF") assert_selector_parses("E, F\nG, H") end def test_expression_fallback_selectors assert_selector_parses('0%') assert_selector_parses('60%') assert_selector_parses('100%') assert_selector_parses('12px') assert_selector_parses('"foo"') end def test_functional_pseudo_selectors assert_selector_parses(':foo("bar")') assert_selector_parses(':foo(bar)') assert_selector_parses(':foo(12px)') assert_selector_parses(':foo(+)') assert_selector_parses(':foo(-)') assert_selector_parses(':foo(+"bar")') assert_selector_parses(':foo(-++--baz-"bar"12px)') end def test_selector_hacks assert_selector_parses('> E') assert_selector_parses('+ E') assert_selector_parses('~ E') assert_selector_parses('>> E') assert_selector_parses('E*') assert_selector_parses('E*.foo') assert_selector_parses('E*:hover') end ## Errors def test_invalid_directives assert_not_parses("identifier", '@ import "foo";') assert_not_parses("identifier", '@12 "foo";') end def test_invalid_classes assert_not_parses("identifier", 'p. foo {a: b}') assert_not_parses("identifier", 'p.1foo {a: b}') end def test_invalid_ids assert_not_parses('"{"', 'p# foo {a: b}') end def test_no_properties_at_toplevel assert_not_parses('pseudoclass or pseudoelement', 'a: b;') end def test_no_scss_directives assert_parses('@import "foo.sass";') assert_parses <$var = 12;") assert_not_parses('"}"', "foo { !var = 12; }") end def test_no_parent_selectors assert_not_parses('"{"', "foo &.bar {a: b}") end def test_no_selector_interpolation assert_not_parses('"{"', 'foo #{"bar"}.baz {a: b}') end def test_no_prop_name_interpolation assert_not_parses('":"', 'foo {a#{"bar"}baz: b}') end def test_no_prop_val_interpolation assert_not_parses('"}"', 'foo {a: b #{"bar"} c}') end def test_no_string_interpolation assert_parses <* c}') end def test_no_nested_rules assert_not_parses('":"', 'foo {bar {a: b}}') assert_not_parses('"}"', 'foo {#bar {a: b}}') end def test_no_nested_properties assert_not_parses('expression (e.g. 1px, bold)', 'foo {bar: {a: b}}') assert_not_parses('expression (e.g. 1px, bold)', 'foo {bar: bang {a: b}}') end def test_no_nested_directives assert_not_parses('"}"', 'foo {@bar {a: b}}') end def test_error_with_windows_newlines render < e assert_equal 'Invalid CSS after "foo {bar": expected ":", was "}"', e.message assert_equal 1, e.sass_line end private def assert_selector_parses(selector) assert_parses <