2009-12-27 03:33:28 -08:00
|
|
|
#!/usr/bin/env ruby
|
2009-12-28 00:11:00 -08:00
|
|
|
require File.dirname(__FILE__) + '/test_helper'
|
2010-01-06 22:42:13 -08:00
|
|
|
require 'sass/scss/css_parser'
|
2009-12-27 03:33:28 -08:00
|
|
|
|
2009-12-28 00:11:00 -08:00
|
|
|
# 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
|
2009-12-27 03:33:28 -08:00
|
|
|
|
|
|
|
def test_basic_scss
|
|
|
|
assert_parses <<SCSS
|
|
|
|
selector {
|
|
|
|
property: value;
|
|
|
|
property2: value; }
|
|
|
|
SCSS
|
|
|
|
|
|
|
|
assert_equal <<CSS, render('sel{p:v}')
|
|
|
|
sel {
|
|
|
|
p: v; }
|
|
|
|
CSS
|
|
|
|
end
|
|
|
|
|
2010-02-02 16:05:52 -08:00
|
|
|
def test_empty_rule
|
|
|
|
assert_equal "", render("#foo .bar {}")
|
|
|
|
assert_equal "", render(<<SCSS)
|
|
|
|
#foo .bar {
|
|
|
|
}
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
2009-12-27 03:33:28 -08:00
|
|
|
def test_cdo_and_cdc_ignored_at_toplevel
|
|
|
|
assert_equal <<CSS, render(<<SCSS)
|
|
|
|
foo {
|
|
|
|
bar: baz; }
|
|
|
|
|
|
|
|
bar {
|
|
|
|
bar: baz; }
|
|
|
|
|
|
|
|
baz {
|
|
|
|
bar: baz; }
|
|
|
|
CSS
|
|
|
|
foo {bar: baz}
|
|
|
|
<!--
|
|
|
|
bar {bar: baz}
|
|
|
|
-->
|
|
|
|
baz {bar: baz}
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
2010-01-05 16:51:45 -08:00
|
|
|
def test_invisible_comments
|
2009-12-27 14:44:05 -08:00
|
|
|
assert_equal <<CSS, render(<<SCSS)
|
|
|
|
foo {
|
|
|
|
a: d; }
|
|
|
|
CSS
|
|
|
|
foo {a: /* b; c: */ d}
|
|
|
|
SCSS
|
|
|
|
assert_equal <<CSS, render(<<SCSS)
|
|
|
|
foo {
|
|
|
|
a: d; }
|
|
|
|
CSS
|
|
|
|
foo {a /*: b; c */: d}
|
|
|
|
SCSS
|
2010-01-05 16:51:45 -08:00
|
|
|
end
|
2009-12-27 14:44:05 -08:00
|
|
|
|
2010-01-05 16:51:45 -08:00
|
|
|
def test_crazy_comments
|
|
|
|
# http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/t040109-c17-comments-00-b.xht
|
|
|
|
assert_equal <<CSS, render(<<SCSS)
|
|
|
|
/* This is a CSS comment. */
|
2009-12-27 14:44:05 -08:00
|
|
|
.one {
|
|
|
|
color: green; }
|
|
|
|
|
2010-01-05 16:51:45 -08:00
|
|
|
/* Another comment */
|
|
|
|
/* The following should not be used:
|
|
|
|
.two {color: red;} */
|
2009-12-27 14:44:05 -08:00
|
|
|
.three {
|
2010-01-05 16:51:45 -08:00
|
|
|
color: green;
|
|
|
|
/* color: red; */ }
|
2009-12-27 14:44:05 -08:00
|
|
|
|
2010-01-05 16:51:45 -08:00
|
|
|
/**
|
|
|
|
.four {color: red;} */
|
2009-12-27 14:44:05 -08:00
|
|
|
.five {
|
|
|
|
color: green; }
|
|
|
|
|
2010-01-05 16:51:45 -08:00
|
|
|
/**/
|
2009-12-27 14:44:05 -08:00
|
|
|
.six {
|
|
|
|
color: green; }
|
|
|
|
|
2010-01-05 16:51:45 -08:00
|
|
|
/*********/
|
2009-12-27 14:44:05 -08:00
|
|
|
.seven {
|
|
|
|
color: green; }
|
|
|
|
|
2010-01-05 16:51:45 -08:00
|
|
|
/* a comment **/
|
2009-12-27 14:44:05 -08:00
|
|
|
.eight {
|
|
|
|
color: green; }
|
|
|
|
CSS
|
|
|
|
/* This is a CSS comment. */
|
|
|
|
.one {color: green;} /* Another comment */
|
|
|
|
/* The following should not be used:
|
|
|
|
.two {color: red;} */
|
|
|
|
.three {color: green; /* color: red; */}
|
|
|
|
/**
|
|
|
|
.four {color: red;} */
|
|
|
|
.five {color: green;}
|
|
|
|
/**/
|
|
|
|
.six {color: green;}
|
|
|
|
/*********/
|
|
|
|
.seven {color: green;}
|
|
|
|
/* a comment **/
|
|
|
|
.eight {color: green;}
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
2010-01-05 16:51:45 -08:00
|
|
|
def test_rule_comments
|
|
|
|
assert_parses <<SCSS
|
|
|
|
/* Foo */
|
|
|
|
.foo {
|
|
|
|
a: b; }
|
|
|
|
SCSS
|
|
|
|
assert_equal <<CSS, render(<<SCSS)
|
|
|
|
/* Foo
|
|
|
|
* Bar */
|
|
|
|
.foo {
|
|
|
|
a: b; }
|
|
|
|
CSS
|
|
|
|
/* Foo
|
|
|
|
* Bar */.foo {
|
|
|
|
a: b; }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_property_comments
|
|
|
|
assert_parses <<SCSS
|
|
|
|
.foo {
|
|
|
|
/* Foo */
|
|
|
|
a: b; }
|
|
|
|
SCSS
|
|
|
|
assert_equal <<CSS, render(<<SCSS)
|
|
|
|
.foo {
|
|
|
|
/* Foo
|
|
|
|
* Bar */
|
|
|
|
a: b; }
|
|
|
|
CSS
|
|
|
|
.foo {
|
|
|
|
/* Foo
|
|
|
|
* Bar */a: b; }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
2010-02-12 13:29:12 -08:00
|
|
|
def test_selector_comments
|
|
|
|
assert_equal <<CSS, render(<<SCSS)
|
|
|
|
.foo #bar:baz( bip) {
|
|
|
|
a: b; }
|
|
|
|
CSS
|
|
|
|
.foo /* .a #foo */ #bar:baz(/* bang )*/ bip) {
|
|
|
|
a: b; }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
2010-01-05 16:51:45 -08:00
|
|
|
def test_lonely_comments
|
|
|
|
assert_parses <<SCSS
|
|
|
|
/* Foo
|
|
|
|
* Bar */
|
|
|
|
SCSS
|
|
|
|
assert_parses <<SCSS
|
|
|
|
.foo {
|
|
|
|
/* Foo
|
|
|
|
* Bar */ }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_multiple_comments
|
|
|
|
assert_parses <<SCSS
|
|
|
|
/* Foo
|
|
|
|
* Bar */
|
|
|
|
/* Baz
|
|
|
|
* Bang */
|
|
|
|
SCSS
|
|
|
|
assert_parses <<SCSS
|
|
|
|
.foo {
|
|
|
|
/* Foo
|
|
|
|
* Bar */
|
|
|
|
/* Baz
|
|
|
|
* Bang */ }
|
|
|
|
SCSS
|
|
|
|
assert_equal <<CSS, render(<<SCSS)
|
|
|
|
.foo {
|
|
|
|
/* Foo Bar */
|
|
|
|
/* Baz Bang */ }
|
|
|
|
CSS
|
|
|
|
.foo {
|
|
|
|
/* Foo Bar *//* Baz Bang */ }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_bizarrely_formatted_comments
|
|
|
|
assert_parses <<SCSS
|
|
|
|
.foo {
|
|
|
|
/* Foo
|
|
|
|
Bar
|
|
|
|
Baz */
|
|
|
|
a: b; }
|
|
|
|
SCSS
|
|
|
|
assert_parses <<SCSS
|
|
|
|
.foo {
|
|
|
|
/* Foo
|
|
|
|
Bar
|
|
|
|
Baz */
|
|
|
|
a: b; }
|
|
|
|
SCSS
|
|
|
|
assert_equal <<CSS, render(<<SCSS)
|
|
|
|
.foo {
|
|
|
|
/* Foo
|
|
|
|
Bar */
|
|
|
|
a: b; }
|
|
|
|
CSS
|
|
|
|
.foo {/* Foo
|
|
|
|
Bar */
|
|
|
|
a: b; }
|
|
|
|
SCSS
|
|
|
|
assert_equal <<CSS, render(<<SCSS)
|
|
|
|
.foo {
|
|
|
|
/* Foo
|
|
|
|
Bar
|
|
|
|
Baz */
|
|
|
|
a: b; }
|
|
|
|
CSS
|
|
|
|
.foo {/* Foo
|
|
|
|
Bar
|
|
|
|
Baz */
|
|
|
|
a: b; }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
2009-12-27 03:33:28 -08:00
|
|
|
## Declarations
|
|
|
|
|
|
|
|
def test_vendor_properties
|
|
|
|
assert_parses <<SCSS
|
|
|
|
foo {
|
|
|
|
-moz-foo-bar: blat;
|
|
|
|
-o-flat-blang: wibble; }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_empty_declarations
|
|
|
|
assert_equal <<CSS, render(<<SCSS)
|
|
|
|
foo {
|
|
|
|
bar: baz; }
|
|
|
|
CSS
|
|
|
|
foo {;;;;
|
|
|
|
bar: baz;;;;
|
|
|
|
;;}
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_basic_property_types
|
|
|
|
assert_parses <<SCSS
|
|
|
|
foo {
|
|
|
|
a: 2;
|
|
|
|
b: 2.3em;
|
|
|
|
c: 50%;
|
|
|
|
d: "fraz bran";
|
|
|
|
e: flanny-blanny-blan;
|
|
|
|
f: url(http://sass-lang.com);
|
|
|
|
g: U+ffa?;
|
|
|
|
h: #abc; }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_functions
|
|
|
|
assert_parses <<SCSS
|
|
|
|
foo {
|
|
|
|
a: foo-bar(12);
|
|
|
|
b: -foo-bar-baz(13, 14 15); }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_unary_minus
|
|
|
|
assert_parses <<SCSS
|
|
|
|
foo {
|
|
|
|
a: -2;
|
|
|
|
b: -2.3em;
|
|
|
|
c: -50%;
|
|
|
|
d: -foo(bar baz); }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_operators
|
|
|
|
assert_parses <<SCSS
|
|
|
|
foo {
|
|
|
|
a: foo bar baz;
|
|
|
|
b: foo, #abc, -12;
|
|
|
|
c: 1px/2px/-3px;
|
|
|
|
d: foo bar, baz/bang; }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_important
|
|
|
|
assert_parses <<SCSS
|
|
|
|
foo {
|
|
|
|
a: foo !important;
|
|
|
|
b: foo bar !important;
|
|
|
|
b: foo, bar !important; }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
2009-12-27 18:02:39 -08:00
|
|
|
def test_initial_hyphen
|
|
|
|
assert_parses <<SCSS
|
|
|
|
foo {
|
|
|
|
a: -moz-bar-baz;
|
|
|
|
b: foo -o-bar-baz; }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
2009-12-27 17:50:11 -08:00
|
|
|
def test_ms_filter_syntax
|
|
|
|
assert_equal <<CSS, render(<<SCSS)
|
|
|
|
foo {
|
|
|
|
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000);
|
|
|
|
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000); }
|
|
|
|
CSS
|
|
|
|
foo {
|
|
|
|
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000);
|
|
|
|
filter:progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000); }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
2009-12-27 18:08:43 -08:00
|
|
|
def test_declaration_hacks
|
|
|
|
assert_parses <<SCSS
|
|
|
|
foo {
|
|
|
|
_name: val;
|
|
|
|
*name: val;
|
2010-02-02 16:08:54 -08:00
|
|
|
:name: val;
|
2010-02-14 12:43:09 -08:00
|
|
|
.name: val;
|
2009-12-27 18:08:43 -08:00
|
|
|
name: val; }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
2009-12-27 18:15:46 -08:00
|
|
|
def test_zero_arg_functions
|
|
|
|
assert_parses <<SCSS
|
|
|
|
foo {
|
|
|
|
a: foo();
|
|
|
|
b: bar baz-bang() bip; }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
2010-02-12 00:35:57 -08:00
|
|
|
def test_expression_function
|
|
|
|
assert_parses <<SCSS
|
|
|
|
foo {
|
|
|
|
a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_calc_function
|
|
|
|
assert_parses <<SCSS
|
|
|
|
foo {
|
|
|
|
a: 12px calc(100%/3 - 2*1em - 2*1px); }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
2009-12-27 03:33:28 -08:00
|
|
|
## Directives
|
|
|
|
|
|
|
|
def test_charset_directive
|
|
|
|
assert_parses '@charset "utf-8";'
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_namespace_directive
|
|
|
|
assert_parses '@namespace "http://www.w3.org/Profiles/xhtml1-strict";'
|
|
|
|
assert_parses '@namespace url(http://www.w3.org/Profiles/xhtml1-strict);'
|
|
|
|
assert_parses '@namespace html url("http://www.w3.org/Profiles/xhtml1-strict");'
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_media_directive
|
|
|
|
assert_parses <<SCSS
|
|
|
|
@media all {
|
|
|
|
rule1 {
|
|
|
|
prop: val; }
|
|
|
|
|
|
|
|
rule2 {
|
|
|
|
prop: val; } }
|
|
|
|
SCSS
|
|
|
|
assert_parses <<SCSS
|
|
|
|
@media screen, print {
|
|
|
|
rule1 {
|
|
|
|
prop: val; }
|
|
|
|
|
|
|
|
rule2 {
|
|
|
|
prop: val; } }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
2010-02-03 00:19:43 -08:00
|
|
|
def test_media_directive_with_keywords
|
|
|
|
assert_parses <<SCSS
|
|
|
|
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
|
|
|
a: b; }
|
|
|
|
SCSS
|
|
|
|
assert_parses <<SCSS
|
|
|
|
@media screen and -webkit-min-device-pixel-ratio: 0 {
|
|
|
|
a: b; }
|
|
|
|
SCSS
|
|
|
|
assert_parses <<SCSS
|
|
|
|
@media screen, print and foo: 0 and bar: 15 {
|
|
|
|
a: b; }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_import_directive_with_media
|
|
|
|
assert_parses '@import "foo.css" screen;'
|
|
|
|
assert_parses '@import "foo.css" screen, print;'
|
|
|
|
assert_parses '@import "foo.css" screen, print and (foo: 0);'
|
|
|
|
assert_parses '@import "foo.css" screen, print and foo: 0;'
|
|
|
|
end
|
|
|
|
|
2009-12-27 03:33:28 -08:00
|
|
|
def test_page_directive
|
|
|
|
assert_parses <<SCSS
|
|
|
|
@page {
|
|
|
|
prop1: val;
|
|
|
|
prop2: val; }
|
|
|
|
SCSS
|
|
|
|
assert_parses <<SCSS
|
|
|
|
@page flap {
|
|
|
|
prop1: val;
|
|
|
|
prop2: val; }
|
|
|
|
SCSS
|
|
|
|
assert_parses <<SCSS
|
|
|
|
@page :first {
|
|
|
|
prop1: val;
|
|
|
|
prop2: val; }
|
|
|
|
SCSS
|
|
|
|
assert_parses <<SCSS
|
|
|
|
@page flap:first {
|
|
|
|
prop1: val;
|
|
|
|
prop2: val; }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_blockless_directive_without_semicolon
|
|
|
|
assert_equal "@charset \"utf-8\";\n", render('@charset "utf-8"')
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_directive_with_lots_of_whitespace
|
|
|
|
assert_equal "@charset \"utf-16\";\n", render('@charset "utf-16" ;')
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_empty_blockless_directive
|
|
|
|
assert_parses "@foo;"
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_multiple_blockless_directives
|
|
|
|
assert_parses <<SCSS
|
|
|
|
@foo bar;
|
|
|
|
@bar baz;
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
2010-02-02 16:05:52 -08:00
|
|
|
def test_empty_block_directive
|
|
|
|
assert_parses "@foo {}"
|
|
|
|
assert_equal "@foo {}\n", render(<<SCSS)
|
|
|
|
@foo {
|
|
|
|
}
|
|
|
|
SCSS
|
|
|
|
end
|
2009-12-27 03:33:28 -08:00
|
|
|
|
|
|
|
def test_multiple_block_directives
|
|
|
|
assert_parses <<SCSS
|
|
|
|
@foo bar {
|
|
|
|
a: b; }
|
|
|
|
|
|
|
|
@bar baz {
|
|
|
|
c: d; }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_block_directive_with_rule_and_property
|
|
|
|
assert_parses <<SCSS
|
|
|
|
@foo {
|
|
|
|
rule {
|
|
|
|
a: b; }
|
|
|
|
|
|
|
|
a: b; }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_block_directive_with_semicolon
|
|
|
|
assert_equal <<CSS, render(<<SCSS)
|
|
|
|
@foo {
|
|
|
|
a: b; }
|
|
|
|
|
|
|
|
@bar {
|
|
|
|
a: b; }
|
|
|
|
CSS
|
|
|
|
@foo {a:b};
|
|
|
|
@bar {a:b};
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
|
|
|
## Selectors
|
|
|
|
|
|
|
|
# Taken from http://www.w3.org/TR/css3-selectors/#selectors
|
|
|
|
def test_summarized_selectors
|
|
|
|
assert_selector_parses('*')
|
|
|
|
assert_selector_parses('E')
|
|
|
|
assert_selector_parses('E[foo]')
|
|
|
|
assert_selector_parses('E[foo="bar"]')
|
|
|
|
assert_selector_parses('E[foo~="bar"]')
|
|
|
|
assert_selector_parses('E[foo^="bar"]')
|
|
|
|
assert_selector_parses('E[foo$="bar"]')
|
|
|
|
assert_selector_parses('E[foo*="bar"]')
|
|
|
|
assert_selector_parses('E[foo|="en"]')
|
|
|
|
assert_selector_parses('E:root')
|
|
|
|
assert_selector_parses('E:nth-child(n)')
|
|
|
|
assert_selector_parses('E:nth-last-child(n)')
|
|
|
|
assert_selector_parses('E:nth-of-type(n)')
|
|
|
|
assert_selector_parses('E:nth-last-of-type(n)')
|
|
|
|
assert_selector_parses('E:first-child')
|
|
|
|
assert_selector_parses('E:last-child')
|
|
|
|
assert_selector_parses('E:first-of-type')
|
|
|
|
assert_selector_parses('E:last-of-type')
|
|
|
|
assert_selector_parses('E:only-child')
|
|
|
|
assert_selector_parses('E:only-of-type')
|
|
|
|
assert_selector_parses('E:empty')
|
|
|
|
assert_selector_parses('E:link')
|
|
|
|
assert_selector_parses('E:visited')
|
|
|
|
assert_selector_parses('E:active')
|
|
|
|
assert_selector_parses('E:hover')
|
|
|
|
assert_selector_parses('E:focus')
|
|
|
|
assert_selector_parses('E:target')
|
|
|
|
assert_selector_parses('E:lang(fr)')
|
|
|
|
assert_selector_parses('E:enabled')
|
|
|
|
assert_selector_parses('E:disabled')
|
|
|
|
assert_selector_parses('E:checked')
|
|
|
|
assert_selector_parses('E::first-line')
|
|
|
|
assert_selector_parses('E::first-letter')
|
|
|
|
assert_selector_parses('E::before')
|
|
|
|
assert_selector_parses('E::after')
|
|
|
|
assert_selector_parses('E.warning')
|
|
|
|
assert_selector_parses('E#myid')
|
|
|
|
assert_selector_parses('E:not(s)')
|
|
|
|
assert_selector_parses('E F')
|
|
|
|
assert_selector_parses('E > 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
|
|
|
|
|
2009-12-27 16:58:03 -08:00
|
|
|
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
|
|
|
|
|
2009-12-27 17:50:11 -08:00
|
|
|
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
|
|
|
|
|
2009-12-27 18:08:43 -08:00
|
|
|
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
|
|
|
|
|
2009-12-27 17:15:52 -08:00
|
|
|
## Errors
|
|
|
|
|
|
|
|
def test_invalid_directives
|
|
|
|
assert_not_parses("identifier", '@<err> import "foo";')
|
|
|
|
assert_not_parses("identifier", '@<err>12 "foo";')
|
|
|
|
end
|
|
|
|
|
2009-12-27 17:30:29 -08:00
|
|
|
def test_invalid_classes
|
|
|
|
assert_not_parses("identifier", 'p.<err> foo {a: b}')
|
|
|
|
assert_not_parses("identifier", 'p.<err>1foo {a: b}')
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_invalid_ids
|
|
|
|
assert_not_parses('"{"', 'p<err># foo {a: b}')
|
|
|
|
end
|
|
|
|
|
2009-12-31 16:24:32 -08:00
|
|
|
def test_no_properties_at_toplevel
|
2010-01-06 22:42:13 -08:00
|
|
|
assert_not_parses('pseudoclass or pseudoelement', 'a:<err> b;')
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_no_scss_directives
|
|
|
|
assert_parses('@import "foo.sass";')
|
|
|
|
assert_parses <<SCSS
|
|
|
|
@mixin foo {
|
|
|
|
a: b; }
|
2009-12-31 16:24:32 -08:00
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
2010-01-06 22:42:13 -08:00
|
|
|
def test_no_variables
|
|
|
|
assert_not_parses("selector or at-rule", "<err>!var = 12;")
|
|
|
|
assert_not_parses('"}"', "foo { <err>!var = 12; }")
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_no_parent_selectors
|
|
|
|
assert_not_parses('"{"', "foo <err>&.bar {a: b}")
|
|
|
|
end
|
2009-12-27 03:33:28 -08:00
|
|
|
|
2010-01-06 22:42:13 -08:00
|
|
|
def test_no_script_values
|
|
|
|
assert_not_parses('":"', "foo {a <err>= b}")
|
2009-12-27 03:33:28 -08:00
|
|
|
end
|
|
|
|
|
2010-01-06 22:42:13 -08:00
|
|
|
def test_no_selector_interpolation
|
|
|
|
assert_not_parses('"{"', 'foo <err>#{"bar"}.baz {a: b}')
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_no_prop_name_interpolation
|
|
|
|
assert_not_parses('":"', 'foo {a<err>#{"bar"}baz: b}')
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_no_prop_val_interpolation
|
|
|
|
assert_not_parses('"}"', 'foo {a: b <err>#{"bar"} c}')
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_no_string_interpolation
|
|
|
|
assert_parses <<SCSS
|
|
|
|
foo {
|
|
|
|
a: "bang \#{1 + "bar"} bip"; }
|
|
|
|
SCSS
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_no_nested_rules
|
|
|
|
assert_not_parses('":"', 'foo {bar <err>{a: b}}')
|
2010-02-14 12:43:09 -08:00
|
|
|
assert_not_parses('"}"', 'foo {<err>#bar {a: b}}')
|
2010-01-06 22:42:13 -08:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_no_nested_properties
|
|
|
|
assert_not_parses('expression (e.g. 1px, bold)', 'foo {bar: <err>{a: b}}')
|
|
|
|
assert_not_parses('expression (e.g. 1px, bold)', 'foo {bar: bang <err>{a: b}}')
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_no_nested_directives
|
|
|
|
assert_not_parses('"}"', 'foo {<err>@bar {a: b}}')
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2009-12-27 03:33:28 -08:00
|
|
|
def assert_selector_parses(selector)
|
|
|
|
assert_parses <<SCSS
|
|
|
|
#{selector} {
|
|
|
|
a: b; }
|
|
|
|
SCSS
|
|
|
|
end
|
2010-01-06 22:42:13 -08:00
|
|
|
|
|
|
|
def render(scss, options = {})
|
|
|
|
tree = Sass::SCSS::CssParser.new(scss).parse
|
|
|
|
tree.options = Sass::Engine::DEFAULT_OPTIONS.merge(options)
|
|
|
|
tree.render
|
|
|
|
end
|
2009-12-27 03:33:28 -08:00
|
|
|
end
|