marcosinger-css_parser 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,69 @@
1
+ # coding: iso-8859-1
2
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
3
+
4
+ # Test cases for CSS regular expressions
5
+ #
6
+ # see http://www.w3.org/TR/CSS21/syndata.html and
7
+ # http://www.w3.org/TR/CSS21/grammar.html
8
+ class CssParserRegexpTests < Test::Unit::TestCase
9
+ def test_strings
10
+ # complete matches
11
+ ['"abcd"', '" A sd s�drcv \'dsf\' asd rfg asd"', '"A\ d??ef 123!"',
12
+ "\"this is\\\n a test\"", '"back\67round"', '"r\000065 ed"',
13
+ "'abcd'", "' A sd sedrcv \"dsf\" asd rf�&23$%#%$g asd'", "'A\\\n def 123!'",
14
+ "'this is\\\n a test'", "'back\\67round'", "'r\\000065 ed'"
15
+ ].each do |str|
16
+ assert_equal str, str.match(CssParser::RE_STRING).to_s
17
+ end
18
+
19
+ test_string = "p { background: red url(\"url\\.'p'ng\"); }"
20
+ assert_equal "\"url\\.'p'ng\"", test_string.match(CssParser::RE_STRING).to_s
21
+
22
+ end
23
+
24
+ def test_unicode
25
+ ['back\67round', 'r\000065 ed', '\00006C'].each do |str|
26
+ assert_match(Regexp.new(CssParser::RE_UNICODE), str)
27
+ end
28
+ end
29
+
30
+ def test_colour
31
+ ['color: #fff', 'color:#f0a09c;', 'color: #04A', 'color: #04a9CE',
32
+ 'color: rgb(100, -10%, 300);', 'color: rgb(10,10,10)', 'color:rgb(12.7253%, -12%,0)',
33
+ 'color: black', 'color:Red;', 'color: AqUa;', 'color: blue ', 'color: transparent'
34
+ ].each do |colour|
35
+ assert_match(CssParser::RE_COLOUR, colour)
36
+ end
37
+
38
+ ['color: #fa', 'color:#f009c;', 'color: #04G', 'color: #04a9Cq',
39
+ 'color: rgb 100, -10%, 300;', 'color: rgb 10,10,10', 'color:rgb(12px, -12%,0)',
40
+ 'color:fuscia;', 'color: thick'
41
+ ].each do |colour|
42
+ assert_no_match(CssParser::RE_COLOUR, colour)
43
+ end
44
+ end
45
+
46
+ def test_uris
47
+ crazy_uri = 'http://www.example.com:80/~/redb%20all.png?test=test&test;test+test#test!'
48
+
49
+ assert_equal "url('#{crazy_uri}')",
50
+ "li { list-style: url('#{crazy_uri}') disc }".match(CssParser::RE_URI).to_s
51
+
52
+ assert_equal "url(#{crazy_uri})",
53
+ "li { list-style: url(#{crazy_uri}) disc }".match(CssParser::RE_URI).to_s
54
+
55
+ assert_equal "url(\"#{crazy_uri}\")",
56
+ "li { list-style: url(\"#{crazy_uri}\") disc }".match(CssParser::RE_URI).to_s
57
+ end
58
+
59
+
60
+ protected
61
+ def load_test_file(filename)
62
+ fh = File.new("fixtures/#{filename}", 'r')
63
+ test_file = fh.read
64
+ fh.close
65
+
66
+ return test_file
67
+ end
68
+
69
+ end
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'net/http'
4
+ require 'open-uri'
5
+ require 'WEBrick'
6
+ require File.dirname(__FILE__) + '/../lib/css_parser'
@@ -0,0 +1,103 @@
1
+ require File.expand_path(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
+
89
+ def test_merging_important
90
+ rs1 = RuleSet.new(nil, 'color: black !important;')
91
+ rs2 = RuleSet.new(nil, 'color: red;')
92
+ merged = CssParser.merge(rs1, rs2)
93
+ assert_equal 'black !important;', merged['color']
94
+ end
95
+
96
+ def test_merging_shorthand_important
97
+ rs1 = RuleSet.new(nil, 'background: black none !important;')
98
+ rs2 = RuleSet.new(nil, 'background-color: red;')
99
+ merged = CssParser.merge(rs1, rs2)
100
+ assert_equal 'black !important;', merged['background-color']
101
+ end
102
+
103
+ end
@@ -0,0 +1,90 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+ require "set"
3
+
4
+ # Test cases for parsing CSS blocks
5
+ class RuleSetTests < Test::Unit::TestCase
6
+ include CssParser
7
+
8
+ def setup
9
+ @cp = Parser.new
10
+ end
11
+
12
+ def test_setting_property_values
13
+ rs = RuleSet.new(nil, nil)
14
+
15
+ rs['background-color'] = 'red'
16
+ assert_equal('red;', rs['background-color'])
17
+
18
+ rs['background-color'] = 'blue !important;'
19
+ assert_equal('blue !important;', rs['background-color'])
20
+ end
21
+
22
+ def test_getting_property_values
23
+ rs = RuleSet.new('#content p, a', 'color: #fff;')
24
+ assert_equal('#fff;', rs['color'])
25
+ end
26
+
27
+ def test_getting_property_value_ignoring_case
28
+ rs = RuleSet.new('#content p, a', 'color: #fff;')
29
+ assert_equal('#fff;', rs[' ColoR '])
30
+ end
31
+
32
+ def test_each_selector
33
+ expected = [
34
+ {:selector => "#content p", :declarations => "color: #fff;", :specificity => 101},
35
+ {:selector => "a", :declarations => "color: #fff;", :specificity => 1}
36
+ ]
37
+
38
+ actual = []
39
+ rs = RuleSet.new('#content p, a', 'color: #fff;')
40
+ rs.each_selector do |sel, decs, spec|
41
+ actual << {:selector => sel, :declarations => decs, :specificity => spec}
42
+ end
43
+
44
+ assert_equal(expected, actual)
45
+ end
46
+
47
+ def test_each_declaration
48
+ expected = Set.new([
49
+ {:property => 'margin', :value => '1px -0.25em', :is_important => false},
50
+ {:property => 'background', :value => 'white none no-repeat', :is_important => true},
51
+ {:property => 'color', :value => '#fff', :is_important => false}
52
+ ])
53
+
54
+ actual = Set.new
55
+ rs = RuleSet.new(nil, 'color: #fff; Background: white none no-repeat !important; margin: 1px -0.25em;')
56
+ rs.each_declaration do |prop, val, imp|
57
+ actual << {:property => prop, :value => val, :is_important => imp}
58
+ end
59
+
60
+ assert_equal(expected, actual)
61
+ end
62
+
63
+ def test_each_declaration_respects_order
64
+ css_fragment = "margin: 0; padding: 20px; margin-bottom: 28px;"
65
+ rs = RuleSet.new(nil, css_fragment)
66
+ expected = %w(margin padding margin-bottom)
67
+ actual = []
68
+ rs.each_declaration { |prop, val, imp| actual << prop }
69
+ assert_equal(expected, actual)
70
+ end
71
+
72
+ def test_declarations_to_s
73
+ declarations = 'color: #fff; font-weight: bold;'
74
+ rs = RuleSet.new('#content p, a', declarations)
75
+ assert_equal(declarations.split(' ').sort, rs.declarations_to_s.split(' ').sort)
76
+ end
77
+
78
+ def test_important_declarations_to_s
79
+ declarations = 'color: #fff; font-weight: bold !important;'
80
+ rs = RuleSet.new('#content p, a', declarations)
81
+ assert_equal(declarations.split(' ').sort, rs.declarations_to_s.split(' ').sort)
82
+ end
83
+
84
+ def test_overriding_specificity
85
+ rs = RuleSet.new('#content p, a', 'color: white', 1000)
86
+ rs.each_selector do |sel, decs, spec|
87
+ assert_equal 1000, spec
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,119 @@
1
+ require File.expand_path(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
+ # ==== Border shorthand
12
+ def test_combining_borders_into_shorthand
13
+ properties = {'border-top-width' => 'auto', 'border-right-width' => 'thin', 'border-bottom-width' => 'auto', 'border-left-width' => '0px'}
14
+
15
+ combined = create_shorthand(properties)
16
+
17
+ assert_equal('auto thin auto 0px;', combined['border-width'])
18
+
19
+ # after creating shorthand, all long-hand properties should be deleted
20
+ assert_properties_are_deleted(combined, properties)
21
+
22
+ # should not combine if any properties are missing
23
+ properties.delete('border-top-width')
24
+
25
+ combined = create_shorthand(properties)
26
+
27
+ assert_equal '', combined['border-width']
28
+
29
+ properties = {'border-width' => '22%', 'border-color' => 'black'}
30
+ combined = create_shorthand(properties)
31
+
32
+ assert_equal '22% black;', combined['border']
33
+ assert_equal '', combined['border-width']
34
+
35
+ properties = {'border-top-style' => 'none', 'border-right-style' => 'none', 'border-bottom-style' => 'none', 'border-left-style' => 'none'}
36
+ combined = create_shorthand(properties)
37
+ assert_equal 'none;', combined['border']
38
+ end
39
+
40
+ # ==== Dimensions shorthand
41
+ def test_combining_dimensions_into_shorthand
42
+ properties = {'margin-right' => 'auto', 'margin-bottom' => '0px', 'margin-left' => 'auto', 'margin-top' => '0px',
43
+ 'padding-right' => '1.25em', 'padding-bottom' => '11%', 'padding-left' => '3pc', 'padding-top' => '11.25ex'}
44
+
45
+ combined = create_shorthand(properties)
46
+
47
+ assert_equal('0px auto;', combined['margin'])
48
+ assert_equal('11.25ex 1.25em 11% 3pc;', combined['padding'])
49
+
50
+ # after creating shorthand, all long-hand properties should be deleted
51
+ assert_properties_are_deleted(combined, properties)
52
+
53
+ # should not combine if any properties are missing
54
+ properties.delete('margin-right')
55
+ properties.delete('padding-right')
56
+
57
+ combined = create_shorthand(properties)
58
+
59
+ assert_equal '', combined['margin']
60
+ assert_equal '', combined['padding']
61
+ end
62
+
63
+ # ==== Font shorthand
64
+ def test_combining_font_into_shorthand
65
+ # should combine if all font properties are present
66
+ properties = {"font-weight" => "300", "font-size" => "12pt",
67
+ "font-family" => "sans-serif", "line-height" => "18px",
68
+ "font-style" => "oblique", "font-variant" => "small-caps"}
69
+
70
+ combined = create_shorthand(properties)
71
+ assert_equal('oblique small-caps 300 12pt/18px sans-serif;', combined['font'])
72
+
73
+ # after creating shorthand, all long-hand properties should be deleted
74
+ assert_properties_are_deleted(combined, properties)
75
+
76
+ # should not combine if any properties are missing
77
+ properties.delete('font-weight')
78
+ combined = create_shorthand(properties)
79
+ assert_equal '', combined['font']
80
+ end
81
+
82
+ # ==== Background shorthand
83
+ def test_combining_background_into_shorthand
84
+ properties = {'background-image' => 'url(\'chess.png\')', 'background-color' => 'gray',
85
+ 'background-position' => 'center -10.2%', 'background-attachment' => 'fixed',
86
+ 'background-repeat' => 'no-repeat'}
87
+
88
+ combined = create_shorthand(properties)
89
+
90
+ assert_equal('gray url(\'chess.png\') no-repeat center -10.2% fixed;', combined['background'])
91
+
92
+ # after creating shorthand, all long-hand properties should be deleted
93
+ assert_properties_are_deleted(combined, properties)
94
+ end
95
+
96
+ def test_property_values_in_url
97
+ 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;")
98
+ rs.expand_shorthand!
99
+ assert_equal('top right;', rs['background-position'])
100
+ rs.create_shorthand!
101
+ assert_equal('url(http://example.com/1528/www/top-logo.jpg) no-repeat top right;', rs['background'])
102
+ end
103
+
104
+ protected
105
+ def assert_properties_are_deleted(ruleset, properties)
106
+ properties.each do |property, value|
107
+ assert_equal '', ruleset[property]
108
+ end
109
+ end
110
+
111
+ def create_shorthand(properties)
112
+ ruleset = RuleSet.new(nil, nil)
113
+ properties.each do |property, value|
114
+ ruleset[property] = value
115
+ end
116
+ ruleset.create_shorthand!
117
+ ruleset
118
+ end
119
+ end
@@ -0,0 +1,198 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+
3
+ class RuleSetExpandingShorthandTests < Test::Unit::TestCase
4
+ include CssParser
5
+
6
+ def setup
7
+ @cp = CssParser::Parser.new
8
+ end
9
+
10
+ # ==== Dimensions shorthand
11
+ def test_expanding_border_shorthand
12
+ declarations = expand_declarations('border: none')
13
+ assert_equal 'none', declarations['border-right-style']
14
+
15
+ declarations = expand_declarations('border: 1px solid red')
16
+ assert_equal '1px', declarations['border-top-width']
17
+ assert_equal 'solid', declarations['border-bottom-style']
18
+
19
+ declarations = expand_declarations('border-color: red hsla(255, 0, 0, 5) rgb(2% ,2%,2%)')
20
+ assert_equal 'red', declarations['border-top-color']
21
+ assert_equal 'rgb(2%,2%,2%)', declarations['border-bottom-color']
22
+ assert_equal 'hsla(255,0,0,5)', declarations['border-left-color']
23
+
24
+ declarations = expand_declarations('border: thin dot-dot-dash')
25
+ assert_equal 'dot-dot-dash', declarations['border-left-style']
26
+ assert_equal 'thin', declarations['border-left-width']
27
+ assert_nil declarations['border-left-color']
28
+ end
29
+
30
+ # ==== Dimensions shorthand
31
+ def test_getting_dimensions_from_shorthand
32
+ # test various shorthand forms
33
+ ['margin: 0px auto', 'margin: 0px auto 0px', 'margin: 0px auto 0px'].each do |shorthand|
34
+ declarations = expand_declarations(shorthand)
35
+ assert_equal({"margin-right" => "auto", "margin-bottom" => "0px", "margin-left" => "auto", "margin-top" => "0px"}, declarations)
36
+ end
37
+
38
+ # test various units
39
+ ['em', 'ex', 'in', 'px', 'pt', 'pc', '%'].each do |unit|
40
+ shorthand = "margin: 0% -0.123#{unit} 9px -.9pc"
41
+ declarations = expand_declarations(shorthand)
42
+ assert_equal({"margin-right" => "-0.123#{unit}", "margin-bottom" => "9px", "margin-left" => "-.9pc", "margin-top" => "0%"}, declarations)
43
+ end
44
+ end
45
+
46
+
47
+ # ==== Font shorthand
48
+ def test_getting_font_size_from_shorthand
49
+ ['em', 'ex', 'in', 'px', 'pt', 'pc', '%'].each do |unit|
50
+ shorthand = "font: 300 italic 11.25#{unit}/14px verdana, helvetica, sans-serif;"
51
+ declarations = expand_declarations(shorthand)
52
+ assert_equal("11.25#{unit}", declarations['font-size'])
53
+ end
54
+
55
+ ['smaller', 'small', 'medium', 'large', 'x-large', 'auto'].each do |unit|
56
+ shorthand = "font: 300 italic #{unit}/14px verdana, helvetica, sans-serif;"
57
+ declarations = expand_declarations(shorthand)
58
+ assert_equal(unit, declarations['font-size'])
59
+ end
60
+ end
61
+
62
+ def test_getting_font_families_from_shorthand
63
+ shorthand = "font: 300 italic 12px/14px \"Helvetica-Neue-Light 45\", 'verdana', helvetica, sans-serif;"
64
+ declarations = expand_declarations(shorthand)
65
+ assert_equal("\"Helvetica-Neue-Light 45\", 'verdana', helvetica, sans-serif", declarations['font-family'])
66
+ end
67
+
68
+ def test_getting_font_weight_from_shorthand
69
+ ['300', 'bold', 'bolder', 'lighter', 'normal'].each do |unit|
70
+ shorthand = "font: #{unit} italic 12px sans-serif;"
71
+ declarations = expand_declarations(shorthand)
72
+ assert_equal(unit, declarations['font-weight'])
73
+ end
74
+
75
+ # ensure normal is the default state
76
+ ['font: normal italic 12px sans-serif;', 'font: italic 12px sans-serif;',
77
+ 'font: small-caps normal 12px sans-serif;', 'font: 12px/16px sans-serif;'].each do |shorthand|
78
+ declarations = expand_declarations(shorthand)
79
+ assert_equal('normal', declarations['font-weight'], shorthand)
80
+ end
81
+ end
82
+
83
+ def test_getting_font_variant_from_shorthand
84
+ shorthand = "font: small-caps italic 12px sans-serif;"
85
+ declarations = expand_declarations(shorthand)
86
+ assert_equal('small-caps', declarations['font-variant'])
87
+
88
+ # ensure normal is the default state
89
+ ['font: normal italic 12px sans-serif;', 'font: italic 12px sans-serif;',
90
+ 'font: normal 12px sans-serif;', 'font: 12px/16px sans-serif;'].each do |shorthand|
91
+ declarations = expand_declarations(shorthand)
92
+ assert_equal('normal', declarations['font-variant'], shorthand)
93
+ end
94
+ end
95
+
96
+ def test_getting_font_style_from_shorthand
97
+ ['italic', 'oblique'].each do |unit|
98
+ shorthand = "font: normal #{unit} bold 12px sans-serif;"
99
+ declarations = expand_declarations(shorthand)
100
+ assert_equal(unit, declarations['font-style'])
101
+ end
102
+
103
+ # ensure normal is the default state
104
+ ['font: normal bold 12px sans-serif;', 'font: small-caps 12px sans-serif;',
105
+ 'font: normal 12px sans-serif;', 'font: 12px/16px sans-serif;'].each do |shorthand|
106
+ declarations = expand_declarations(shorthand)
107
+ assert_equal('normal', declarations['font-style'], shorthand)
108
+ end
109
+ end
110
+
111
+ def test_getting_line_height_from_shorthand
112
+ ['em', 'ex', 'in', 'px', 'pt', 'pc', '%'].each do |unit|
113
+ shorthand = "font: 300 italic 12px/0.25#{unit} verdana, helvetica, sans-serif;"
114
+ declarations = expand_declarations(shorthand)
115
+ assert_equal("0.25#{unit}", declarations['line-height'])
116
+ end
117
+
118
+ # ensure normal is the default state
119
+ ['font: normal bold 12px sans-serif;', 'font: small-caps 12px sans-serif;',
120
+ 'font: normal 12px sans-serif;', 'font: 12px sans-serif;'].each do |shorthand|
121
+ declarations = expand_declarations(shorthand)
122
+ assert_equal('normal', declarations['line-height'], shorthand)
123
+ end
124
+ end
125
+
126
+
127
+ # ==== Background shorthand
128
+ def test_getting_background_properties_from_shorthand
129
+ expected = {"background-image" => "url('chess.png')", "background-color" => "gray", "background-repeat" => "repeat",
130
+ "background-attachment" => "fixed", "background-position" => "50%"}
131
+
132
+ shorthand = "background: url('chess.png') gray 50% repeat fixed;"
133
+ declarations = expand_declarations(shorthand)
134
+ assert_equal expected, declarations
135
+ end
136
+
137
+ def test_getting_background_position_from_shorthand
138
+ ['em', 'ex', 'in', 'px', 'pt', 'pc', '%'].each do |unit|
139
+ shorthand = "background: url('chess.png') gray 30% -0.15#{unit} repeat fixed;"
140
+ declarations = expand_declarations(shorthand)
141
+ assert_equal("30% -0.15#{unit}", declarations['background-position'])
142
+ end
143
+
144
+ ['left', 'center', 'right', 'top', 'bottom', 'inherit'].each do |position|
145
+ shorthand = "background: url('chess.png') #000fff #{position} no-repeat fixed;"
146
+ declarations = expand_declarations(shorthand)
147
+ assert_equal(position, declarations['background-position'])
148
+ end
149
+ end
150
+
151
+ def test_getting_background_colour_from_shorthand
152
+ ['blue', 'lime', 'rgb(10,10,10)', 'rgb ( -10%, 99, 300)', '#ffa0a0', '#03c', 'trAnsparEnt', 'inherit'].each do |colour|
153
+ shorthand = "background:#{colour} url('chess.png') center repeat fixed ;"
154
+ declarations = expand_declarations(shorthand)
155
+ assert_equal(colour, declarations['background-color'])
156
+ end
157
+ end
158
+
159
+ def test_getting_background_attachment_from_shorthand
160
+ ['scroll', 'fixed', 'inherit'].each do |attachment|
161
+ shorthand = "background:#0f0f0f url('chess.png') center repeat #{attachment};"
162
+ declarations = expand_declarations(shorthand)
163
+ assert_equal(attachment, declarations['background-attachment'])
164
+ end
165
+ end
166
+
167
+ def test_getting_background_repeat_from_shorthand
168
+ ['repeat-x', 'repeat-y', 'no-repeat', 'inherit'].each do |repeat|
169
+ shorthand = "background:#0f0f0f none #{repeat};"
170
+ declarations = expand_declarations(shorthand)
171
+ assert_equal(repeat, declarations['background-repeat'])
172
+ end
173
+ end
174
+
175
+ def test_getting_background_image_from_shorthand
176
+ ['url("chess.png")', 'url("https://example.org:80/~files/chess.png?123=abc&test#5")',
177
+ 'url(https://example.org:80/~files/chess.png?123=abc&test#5)',
178
+ "url('https://example.org:80/~files/chess.png?123=abc&test#5')", 'none', 'inherit'].each do |image|
179
+
180
+ shorthand = "background: #0f0f0f #{image} ;"
181
+ declarations = expand_declarations(shorthand)
182
+ assert_equal(image, declarations['background-image'])
183
+ end
184
+ end
185
+
186
+
187
+ protected
188
+ def expand_declarations(declarations)
189
+ ruleset = RuleSet.new(nil, declarations)
190
+ ruleset.expand_shorthand!
191
+
192
+ collected = {}
193
+ ruleset.each_declaration do |prop, val, imp|
194
+ collected[prop.to_s] = val.to_s
195
+ end
196
+ collected
197
+ end
198
+ end