css_parser 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +33 -0
- data/LICENSE +42 -0
- data/README +60 -0
- data/lib/css_parser/parser.rb +345 -0
- data/lib/css_parser/regexps.rb +46 -0
- data/lib/css_parser/rule_set.rb +381 -0
- data/lib/css_parser.rb +149 -0
- data/test/fixtures/import-circular-reference.css +4 -0
- data/test/fixtures/import-with-media-types.css +3 -0
- data/test/fixtures/import1.css +3 -0
- data/test/fixtures/simple.css +6 -0
- data/test/fixtures/subdir/import2.css +3 -0
- data/test/test_css_parser_basic.rb +56 -0
- data/test/test_css_parser_downloading.rb +81 -0
- data/test/test_css_parser_media_types.rb +71 -0
- data/test/test_css_parser_misc.rb +143 -0
- data/test/test_css_parser_regexps.rb +68 -0
- data/test/test_helper.rb +8 -0
- data/test/test_merging.rb +88 -0
- data/test/test_rule_set.rb +74 -0
- data/test/test_rule_set_creating_shorthand.rb +90 -0
- data/test/test_rule_set_expanding_shorthand.rb +178 -0
- metadata +82 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
# Test cases for the handling of media types
|
4
|
+
class CssParserMediaTypesTests < Test::Unit::TestCase
|
5
|
+
include CssParser
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@cp = Parser.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_finding_by_media_type
|
12
|
+
# from http://www.w3.org/TR/CSS21/media.html#at-media-rule
|
13
|
+
css = <<-EOT
|
14
|
+
@media print {
|
15
|
+
body { font-size: 10pt }
|
16
|
+
}
|
17
|
+
@media screen {
|
18
|
+
body { font-size: 13px }
|
19
|
+
}
|
20
|
+
@media screen, print {
|
21
|
+
body { line-height: 1.2 }
|
22
|
+
}
|
23
|
+
EOT
|
24
|
+
|
25
|
+
@cp.add_block!(css)
|
26
|
+
|
27
|
+
assert_equal 'font-size: 10pt; line-height: 1.2;', @cp.find_by_selector('body', :print).join(' ')
|
28
|
+
assert_equal 'font-size: 13px; line-height: 1.2;', @cp.find_by_selector('body', :screen).join(' ')
|
29
|
+
end
|
30
|
+
|
31
|
+
def atest_finding_by_multiple_media_types
|
32
|
+
css = <<-EOT
|
33
|
+
@media print {
|
34
|
+
body { font-size: 10pt }
|
35
|
+
}
|
36
|
+
@media handheld {
|
37
|
+
body { font-size: 13px }
|
38
|
+
}
|
39
|
+
@media screen, print {
|
40
|
+
body { line-height: 1.2 }
|
41
|
+
}
|
42
|
+
EOT
|
43
|
+
@cp.add_block!(css)
|
44
|
+
|
45
|
+
assert_equal 'font-size: 13px; line-height: 1.2;', @cp.find_by_selector('body', [:screen,:handheld]).join(' ')
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_adding_block_with_media_types
|
49
|
+
css = <<-EOT
|
50
|
+
body { font-size: 10pt }
|
51
|
+
EOT
|
52
|
+
|
53
|
+
@cp.add_block!(css, :media_types => [:screen])
|
54
|
+
|
55
|
+
assert_equal 'font-size: 10pt;', @cp.find_by_selector('body', :screen).join(' ')
|
56
|
+
assert @cp.find_by_selector('body', :handheld).empty?
|
57
|
+
end
|
58
|
+
|
59
|
+
def atest_adding_rule_set_with_media_type
|
60
|
+
@cp.add_rule!('body', 'color: black;', [:handheld,:tty])
|
61
|
+
@cp.add_rule!('body', 'color: blue;', :screen)
|
62
|
+
assert_equal 'color: black;', @cp.find_by_selector('body', :handheld).join(' ')
|
63
|
+
end
|
64
|
+
|
65
|
+
def atest_selecting_with_all_meda_type
|
66
|
+
@cp.add_rule!('body', 'color: black;', [:handheld,:tty])
|
67
|
+
assert_equal 'color: black;', @cp.find_by_selector('body', :all).join(' ')
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
# Test cases for the CssParser.
|
4
|
+
class CssParserTests < Test::Unit::TestCase
|
5
|
+
include CssParser
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@cp = Parser.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_at_page_rule
|
12
|
+
# from http://www.w3.org/TR/CSS21/page.html#page-selectors
|
13
|
+
css = <<-EOT
|
14
|
+
@page { margin: 2cm }
|
15
|
+
|
16
|
+
@page :first {
|
17
|
+
margin-top: 10cm
|
18
|
+
}
|
19
|
+
EOT
|
20
|
+
|
21
|
+
@cp.add_block!(css)
|
22
|
+
|
23
|
+
assert_equal 'margin: 2cm;', @cp.find_by_selector('@page').join(' ')
|
24
|
+
assert_equal 'margin-top: 10cm;', @cp.find_by_selector('@page :first').join(' ')
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_should_ignore_comments
|
28
|
+
# see http://www.w3.org/Style/CSS/Test/CSS2.1/current/html4/t040109-c17-comments-00-b.htm
|
29
|
+
css =<<-EOT
|
30
|
+
/* This is a CSS comment. */
|
31
|
+
.one {color: green;} /* Another comment */
|
32
|
+
/* The following should not be used:
|
33
|
+
.one {color: red;} */
|
34
|
+
.two {color: green; /* color: yellow; */}
|
35
|
+
/**
|
36
|
+
.three {color: red;} */
|
37
|
+
.three {color: green;}
|
38
|
+
/**/
|
39
|
+
.four {color: green;}
|
40
|
+
/*********/
|
41
|
+
.five {color: green;}
|
42
|
+
/* a comment **/
|
43
|
+
.six {color: green;}
|
44
|
+
EOT
|
45
|
+
|
46
|
+
@cp.add_block!(css)
|
47
|
+
@cp.each_selector do |sel, decs, spec|
|
48
|
+
assert_equal 'color: green;', decs
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_parsing_blocks
|
53
|
+
# dervived from http://www.w3.org/TR/CSS21/syndata.html#rule-sets
|
54
|
+
css = <<-EOT
|
55
|
+
div[name='test'] {
|
56
|
+
|
57
|
+
color:
|
58
|
+
|
59
|
+
red;
|
60
|
+
|
61
|
+
}div:hover{coloR:red;
|
62
|
+
}div:first-letter{color:red;/*color:blue;}"commented out"*/}
|
63
|
+
|
64
|
+
p[example="public class foo\
|
65
|
+
{\
|
66
|
+
private string x;\
|
67
|
+
\
|
68
|
+
foo(int x) {\
|
69
|
+
this.x = 'test';\
|
70
|
+
this.x = \"test\";\
|
71
|
+
}\
|
72
|
+
\
|
73
|
+
}"] { color: red }
|
74
|
+
|
75
|
+
p { color:red}
|
76
|
+
EOT
|
77
|
+
|
78
|
+
@cp.add_block!(css)
|
79
|
+
|
80
|
+
@cp.each_selector do |sel, decs, spec|
|
81
|
+
assert_equal 'color: red;', decs
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_ignoring_malformed_declarations
|
86
|
+
flunk
|
87
|
+
# dervived from http://www.w3.org/TR/CSS21/syndata.html#parsing-errors
|
88
|
+
css = <<-EOT
|
89
|
+
p { color:green }
|
90
|
+
p { color:green; color } /* malformed declaration missing ':', value */
|
91
|
+
p { color:red; color; color:green } /* same with expected recovery */
|
92
|
+
p { color:green; color: } /* malformed declaration missing value */
|
93
|
+
p { color:red; color:; color:green } /* same with expected recovery */
|
94
|
+
p { color:green; color{;color:maroon} } /* unexpected tokens { } */
|
95
|
+
p { color:red; color{;color:maroon}; color:green } /* same with recovery */
|
96
|
+
EOT
|
97
|
+
|
98
|
+
@cp.add_block!(css)
|
99
|
+
|
100
|
+
@cp.each_selector do |sel, decs, spec|
|
101
|
+
assert_equal 'color: green;', decs
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_calculating_specificity
|
106
|
+
# from http://www.w3.org/TR/CSS21/cascade.html#specificity
|
107
|
+
assert_equal 0, CssParser.calculate_specificity('*')
|
108
|
+
assert_equal 1, CssParser.calculate_specificity('li')
|
109
|
+
assert_equal 2, CssParser.calculate_specificity('li:first-line')
|
110
|
+
assert_equal 2, CssParser.calculate_specificity('ul li')
|
111
|
+
assert_equal 3, CssParser.calculate_specificity('ul ol+li')
|
112
|
+
assert_equal 11, CssParser.calculate_specificity('h1 + *[rel=up]')
|
113
|
+
assert_equal 13, CssParser.calculate_specificity('ul ol li.red')
|
114
|
+
assert_equal 21, CssParser.calculate_specificity('li.red.level')
|
115
|
+
assert_equal 100, CssParser.calculate_specificity('#x34y')
|
116
|
+
|
117
|
+
# from http://www.hixie.ch/tests/adhoc/css/cascade/specificity/003.html
|
118
|
+
assert_equal CssParser.calculate_specificity('div *'), CssParser.calculate_specificity('p')
|
119
|
+
assert CssParser.calculate_specificity('body div *') > CssParser.calculate_specificity('div *')
|
120
|
+
|
121
|
+
# other tests
|
122
|
+
assert_equal 11, CssParser.calculate_specificity('h1[id|=123]')
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_converting_uris
|
126
|
+
base_uri = 'http://www.example.org/style/basic.css'
|
127
|
+
["body { background: url(yellow) };", "body { background: url('yellow') };",
|
128
|
+
"body { background: url('/style/yellow') };",
|
129
|
+
"body { background: url(\"../style/yellow\") };",
|
130
|
+
"body { background: url(\"lib/../../style/yellow\") };"].each do |css|
|
131
|
+
converted_css = CssParser.convert_uris(css, base_uri)
|
132
|
+
assert_equal "body { background: url('http://www.example.org/style/yellow') };", converted_css
|
133
|
+
end
|
134
|
+
|
135
|
+
converted_css = CssParser.convert_uris("body { background: url(../style/yellow-dot_symbol$.png?abc=123&def=456&ghi=789#1011) };", base_uri)
|
136
|
+
assert_equal "body { background: url('http://www.example.org/style/yellow-dot_symbol$.png?abc=123&def=456&ghi=789#1011') };", converted_css
|
137
|
+
|
138
|
+
# taken from error log: 2007-10-23 04:37:41#2399
|
139
|
+
converted_css = CssParser.convert_uris('.specs {font-family:Helvetica;font-weight:bold;font-style:italic;color:#008CA8;font-size:1.4em;list-style-image:url("images/bullet.gif");}', 'http://www.example.org/directory/file.html')
|
140
|
+
assert_equal ".specs {font-family:Helvetica;font-weight:bold;font-style:italic;color:#008CA8;font-size:1.4em;list-style-image:url('http://www.example.org/directory/images/bullet.gif');}", converted_css
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
# Test cases for CSS regular expressions
|
4
|
+
#
|
5
|
+
# see http://www.w3.org/TR/CSS21/syndata.html and
|
6
|
+
# http://www.w3.org/TR/CSS21/grammar.html
|
7
|
+
class CssParserRegexpTests < Test::Unit::TestCase
|
8
|
+
def test_strings
|
9
|
+
# complete matches
|
10
|
+
['"abcd"', '" A sd s�drcv \'dsf\' asd rfg asd"', '"A\ d??ef 123!"',
|
11
|
+
"\"this is\\\n a test\"", '"back\67round"', '"r\000065 ed"',
|
12
|
+
"'abcd'", "' A sd sedrcv \"dsf\" asd rf�&23$%#%$g asd'", "'A\\\n def 123!'",
|
13
|
+
"'this is\\\n a test'", "'back\\67round'", "'r\\000065 ed'"
|
14
|
+
].each do |str|
|
15
|
+
assert_equal str, str.match(CssParser::RE_STRING).to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
test_string = "p { background: red url(\"url\\.'p'ng\"); }"
|
19
|
+
assert_equal "\"url\\.'p'ng\"", test_string.match(CssParser::RE_STRING).to_s
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_unicode
|
24
|
+
['back\67round', 'r\000065 ed', '\00006C'].each do |str|
|
25
|
+
assert_match(Regexp.new(CssParser::RE_UNICODE), str)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_colour
|
30
|
+
['color: #fff', 'color:#f0a09c;', 'color: #04A', 'color: #04a9CE',
|
31
|
+
'color: rgb(100, -10%, 300);', 'color: rgb(10,10,10)', 'color:rgb(12.7253%, -12%,0)',
|
32
|
+
'color: black', 'color:Red;', 'color: AqUa;', 'color: blue ', 'color: transparent'
|
33
|
+
].each do |colour|
|
34
|
+
assert_match(CssParser::RE_COLOUR, colour)
|
35
|
+
end
|
36
|
+
|
37
|
+
['color: #fa', 'color:#f009c;', 'color: #04G', 'color: #04a9Cq',
|
38
|
+
'color: rgb 100, -10%, 300;', 'color: rgb 10,10,10', 'color:rgb(12px, -12%,0)',
|
39
|
+
'color:fuscia;', 'color: thick'
|
40
|
+
].each do |colour|
|
41
|
+
assert_no_match(CssParser::RE_COLOUR, colour)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_uris
|
46
|
+
crazy_uri = 'http://www.example.com:80/~/redb%20all.png?test=test&test;test+test#test!'
|
47
|
+
|
48
|
+
assert_equal "url('#{crazy_uri}')",
|
49
|
+
"li { list-style: url('#{crazy_uri}') disc }".match(CssParser::RE_URI).to_s
|
50
|
+
|
51
|
+
assert_equal "url(#{crazy_uri})",
|
52
|
+
"li { list-style: url(#{crazy_uri}) disc }".match(CssParser::RE_URI).to_s
|
53
|
+
|
54
|
+
assert_equal "url(\"#{crazy_uri}\")",
|
55
|
+
"li { list-style: url(\"#{crazy_uri}\") disc }".match(CssParser::RE_URI).to_s
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
protected
|
60
|
+
def load_test_file(filename)
|
61
|
+
fh = File.new("fixtures/#{filename}", 'r')
|
62
|
+
test_file = fh.read
|
63
|
+
fh.close
|
64
|
+
|
65
|
+
return test_file
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__), '../'))
|
2
|
+
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__), '../lib/'))
|
3
|
+
require 'rubygems'
|
4
|
+
require 'test/unit'
|
5
|
+
require 'css_parser'
|
6
|
+
require 'net/http'
|
7
|
+
require 'open-uri'
|
8
|
+
require 'WEBrick'
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class MergingTests < Test::Unit::TestCase
|
4
|
+
include CssParser
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@cp = CssParser::Parser.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_simple_merge
|
11
|
+
rs1 = RuleSet.new(nil, 'color: black;')
|
12
|
+
rs2 = RuleSet.new(nil, 'margin: 0px;')
|
13
|
+
merged = CssParser.merge(rs1, rs2)
|
14
|
+
assert_equal '0px;', merged['margin']
|
15
|
+
assert_equal 'black;', merged['color']
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_merging_array
|
19
|
+
rs1 = RuleSet.new(nil, 'color: black;')
|
20
|
+
rs2 = RuleSet.new(nil, 'margin: 0px;')
|
21
|
+
merged = CssParser.merge([rs1, rs2])
|
22
|
+
assert_equal '0px;', merged['margin']
|
23
|
+
assert_equal 'black;', merged['color']
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def test_merging_multiple
|
28
|
+
rs1 = RuleSet.new(nil, 'color: black;')
|
29
|
+
rs2 = RuleSet.new(nil, 'margin: 0px;')
|
30
|
+
rs3 = RuleSet.new(nil, 'margin: 5px;')
|
31
|
+
merged = CssParser.merge(rs1, rs2, rs3)
|
32
|
+
assert_equal '5px;', merged['margin']
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_multiple_selectors_should_have_zero_specificity
|
36
|
+
rs1 = RuleSet.new('p, a[rel="external"]', 'color: black;')
|
37
|
+
rs2 = RuleSet.new('a', 'color: blue;')
|
38
|
+
merged = CssParser.merge(rs1, rs2)
|
39
|
+
assert_equal 'blue;', merged['color']
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_setting_specificity
|
43
|
+
rs1 = RuleSet.new(nil, 'color: red;', 20)
|
44
|
+
rs2 = RuleSet.new(nil, 'color: blue;', 10)
|
45
|
+
merged = CssParser.merge(rs1, rs2)
|
46
|
+
assert_equal 'red;', merged['color']
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_properties_should_be_case_insensitive
|
50
|
+
rs1 = RuleSet.new(nil, ' CoLor : red ;', 20)
|
51
|
+
rs2 = RuleSet.new(nil, 'color: blue;', 10)
|
52
|
+
merged = CssParser.merge(rs1, rs2)
|
53
|
+
assert_equal 'red;', merged['color']
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_merging_backgrounds
|
57
|
+
rs1 = RuleSet.new(nil, 'background-color: black;')
|
58
|
+
rs2 = RuleSet.new(nil, 'background-image: none;')
|
59
|
+
merged = CssParser.merge(rs1, rs2)
|
60
|
+
assert_equal 'black none;', merged['background']
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_merging_dimensions
|
64
|
+
rs1 = RuleSet.new(nil, 'margin: 3em;')
|
65
|
+
rs2 = RuleSet.new(nil, 'margin-left: 1em;')
|
66
|
+
merged = CssParser.merge(rs1, rs2)
|
67
|
+
assert_equal '3em 3em 3em 1em;', merged['margin']
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_merging_fonts
|
71
|
+
rs1 = RuleSet.new(nil, 'font: 11px Arial;')
|
72
|
+
rs2 = RuleSet.new(nil, 'font-weight: bold;')
|
73
|
+
merged = CssParser.merge(rs1, rs2)
|
74
|
+
assert_equal 'bold 11px Arial;', merged['font']
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_raising_error_on_bad_type
|
78
|
+
assert_raise ArgumentError do
|
79
|
+
CssParser.merge([1,2,3])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_returning_early_with_only_one_params
|
84
|
+
rs = RuleSet.new(nil, 'font-weight: bold;')
|
85
|
+
merged = CssParser.merge(rs)
|
86
|
+
assert_equal rs.object_id, merged.object_id
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
# Test cases for parsing CSS blocks
|
4
|
+
class RuleSetTests < Test::Unit::TestCase
|
5
|
+
include CssParser
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@cp = Parser.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_setting_property_values
|
12
|
+
rs = RuleSet.new(nil, nil)
|
13
|
+
|
14
|
+
rs['background-color'] = 'red'
|
15
|
+
assert_equal('red;', rs['background-color'])
|
16
|
+
|
17
|
+
rs['background-color'] = 'blue !important;'
|
18
|
+
assert_equal('blue !important;', rs['background-color'])
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_getting_property_values
|
22
|
+
rs = RuleSet.new('#content p, a', 'color: #fff;')
|
23
|
+
assert_equal('#fff;', rs['color'])
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_getting_property_value_ignoring_case
|
27
|
+
rs = RuleSet.new('#content p, a', 'color: #fff;')
|
28
|
+
assert_equal('#fff;', rs[' ColoR '])
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_each_selector
|
32
|
+
expected = [
|
33
|
+
{:selector => "#content p", :declarations => "color: #fff;", :specificity => 101},
|
34
|
+
{:selector => "a", :declarations => "color: #fff;", :specificity => 1}
|
35
|
+
]
|
36
|
+
|
37
|
+
actual = []
|
38
|
+
rs = RuleSet.new('#content p, a', 'color: #fff;')
|
39
|
+
rs.each_selector do |sel, decs, spec|
|
40
|
+
actual << {:selector => sel, :declarations => decs, :specificity => spec}
|
41
|
+
end
|
42
|
+
|
43
|
+
assert_equal(expected, actual)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_each_declaration
|
47
|
+
expected = [
|
48
|
+
{:property => 'margin', :value => '1px -0.25em', :is_important => false},
|
49
|
+
{:property => 'background', :value => 'white none no-repeat', :is_important => true},
|
50
|
+
{:property => 'color', :value => '#fff', :is_important => false}
|
51
|
+
]
|
52
|
+
|
53
|
+
actual = []
|
54
|
+
rs = RuleSet.new(nil, 'color: #fff; Background: white none no-repeat !important; margin: 1px -0.25em;')
|
55
|
+
rs.each_declaration do |prop, val, imp|
|
56
|
+
actual << {:property => prop, :value => val, :is_important => imp}
|
57
|
+
end
|
58
|
+
|
59
|
+
assert_equal(expected, actual)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_declarations_to_s
|
63
|
+
declarations = 'color: #fff; font-weight: bold;'
|
64
|
+
rs = RuleSet.new('#content p, a', declarations)
|
65
|
+
assert_equal(declarations.split(' ').sort, rs.declarations_to_s.split(' ').sort)
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_overriding_specificity
|
69
|
+
rs = RuleSet.new('#content p, a', 'color: white', 1000)
|
70
|
+
rs.each_selector do |sel, decs, spec|
|
71
|
+
assert_equal 1000, spec
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
# Test cases for reading and generating CSS shorthand properties
|
4
|
+
class RuleSetCreatingShorthandTests < Test::Unit::TestCase
|
5
|
+
include CssParser
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@cp = CssParser::Parser.new
|
9
|
+
end
|
10
|
+
|
11
|
+
# ==== Dimensions shorthand
|
12
|
+
def test_combining_dimensions_into_shorthand
|
13
|
+
properties = {'margin-right' => 'auto', 'margin-bottom' => '0px', 'margin-left' => 'auto', 'margin-top' => '0px',
|
14
|
+
'padding-right' => '1.25em', 'padding-bottom' => '11%', 'padding-left' => '3pc', 'padding-top' => '11.25ex'}
|
15
|
+
|
16
|
+
combined = create_shorthand(properties)
|
17
|
+
|
18
|
+
assert_equal('0px auto;', combined['margin'])
|
19
|
+
assert_equal('11.25ex 1.25em 11% 3pc;', combined['padding'])
|
20
|
+
|
21
|
+
# after creating shorthand, all long-hand properties should be deleted
|
22
|
+
assert_properties_are_deleted(combined, properties)
|
23
|
+
|
24
|
+
# should not combine if any properties are missing
|
25
|
+
properties.delete('margin-right')
|
26
|
+
properties.delete('padding-right')
|
27
|
+
|
28
|
+
combined = create_shorthand(properties)
|
29
|
+
|
30
|
+
assert_equal '', combined['margin']
|
31
|
+
assert_equal '', combined['padding']
|
32
|
+
end
|
33
|
+
|
34
|
+
# ==== Font shorthand
|
35
|
+
def test_combining_font_into_shorthand
|
36
|
+
# should combine if all font properties are present
|
37
|
+
properties = {"font-weight" => "300", "font-size" => "12pt",
|
38
|
+
"font-family" => "sans-serif", "line-height" => "18px",
|
39
|
+
"font-style" => "oblique", "font-variant" => "small-caps"}
|
40
|
+
|
41
|
+
combined = create_shorthand(properties)
|
42
|
+
assert_equal('oblique small-caps 300 12pt/18px sans-serif;', combined['font'])
|
43
|
+
|
44
|
+
# after creating shorthand, all long-hand properties should be deleted
|
45
|
+
assert_properties_are_deleted(combined, properties)
|
46
|
+
|
47
|
+
# should not combine if any properties are missing
|
48
|
+
properties.delete('font-weight')
|
49
|
+
combined = create_shorthand(properties)
|
50
|
+
assert_equal '', combined['font']
|
51
|
+
end
|
52
|
+
|
53
|
+
# ==== Background shorthand
|
54
|
+
def test_combining_background_into_shorthand
|
55
|
+
properties = {'background-image' => 'url(\'chess.png\')', 'background-color' => 'gray',
|
56
|
+
'background-position' => 'center -10.2%', 'background-attachment' => 'fixed',
|
57
|
+
'background-repeat' => 'no-repeat'}
|
58
|
+
|
59
|
+
combined = create_shorthand(properties)
|
60
|
+
|
61
|
+
assert_equal('gray url(\'chess.png\') no-repeat center -10.2% fixed;', combined['background'])
|
62
|
+
|
63
|
+
# after creating shorthand, all long-hand properties should be deleted
|
64
|
+
assert_properties_are_deleted(combined, properties)
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_property_values_in_url
|
68
|
+
rs = RuleSet.new('#header', "background:url(http://example.com/1528/www/top-logo.jpg) no-repeat top right; padding: 79px 0 10px 0; text-align:left;")
|
69
|
+
rs.expand_shorthand!
|
70
|
+
assert_equal('top right;', rs['background-position'])
|
71
|
+
rs.create_shorthand!
|
72
|
+
assert_equal('url(http://example.com/1528/www/top-logo.jpg) no-repeat top right;', rs['background'])
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
def assert_properties_are_deleted(ruleset, properties)
|
77
|
+
properties.each do |property, value|
|
78
|
+
assert_equal '', ruleset[property]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def create_shorthand(properties)
|
83
|
+
ruleset = RuleSet.new(nil, nil)
|
84
|
+
properties.each do |property, value|
|
85
|
+
ruleset[property] = value
|
86
|
+
end
|
87
|
+
ruleset.create_shorthand!
|
88
|
+
ruleset
|
89
|
+
end
|
90
|
+
end
|