premailer 1.7.1 → 1.7.3

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.
@@ -0,0 +1,233 @@
1
+ # encoding: UTF-8
2
+ require File.expand_path(File.dirname(__FILE__)) + '/helper'
3
+
4
+ # Random tests for specific issues.
5
+ #
6
+ # The test suite will be cleaned up at some point soon.
7
+ class TestMisc < Test::Unit::TestCase
8
+
9
+ # in response to http://github.com/alexdunae/premailer/issues#issue/4
10
+ #
11
+ # NB: 2010-11-16 -- after reverting to Hpricot this test can no longer pass.
12
+ # It's too much of an edge case to get any dev time.
13
+ def test_parsing_extra_quotes
14
+ io = StringIO.new('<p></p>
15
+ <h3 "id="WAR"><a name="WAR"></a>Writes and Resources</h3>
16
+ <table></table>')
17
+ premailer = Premailer.new(io, :adapter => :nokogiri)
18
+ assert_match /<h3>[\s]*<a name="WAR">[\s]*<\/a>[\s]*Writes and Resources[\s]*<\/h3>/i, premailer.to_inline_css
19
+ end
20
+
21
+ def test_styles_in_the_body
22
+ html = <<END_HTML
23
+ <html>
24
+ <body>
25
+ <style type="text/css"> p { color: red; } </style>
26
+ <p>Test</p>
27
+ </body>
28
+ </html>
29
+ END_HTML
30
+
31
+ premailer = Premailer.new(html, :with_html_string => true)
32
+ premailer.to_inline_css
33
+
34
+ assert_match /color\: red/i, premailer.processed_doc.at('p')['style']
35
+ end
36
+
37
+ def test_commented_out_styles_in_the_body
38
+ html = <<END_HTML
39
+ <html>
40
+ <body>
41
+ <style type="text/css"> <!-- p { color: red; } --> </style>
42
+ <p>Test</p>
43
+ </body>
44
+ </html>
45
+ END_HTML
46
+
47
+ premailer = Premailer.new(html, :with_html_string => true)
48
+ premailer.to_inline_css
49
+
50
+ assert_match /color\: red/i, premailer.processed_doc.at('p')['style']
51
+ end
52
+
53
+ def test_not_applying_styles_to_the_head
54
+ html = <<END_HTML
55
+ <html>
56
+ <head>
57
+ <title>Title</title>
58
+ <style type="text/css"> * { color: red; } </style>
59
+ </head>
60
+ <body>
61
+ <p><a>Test</a></p>
62
+ </body>
63
+ </html>
64
+ END_HTML
65
+
66
+ [:nokogiri, :hpricot].each do |adapter|
67
+ premailer = Premailer.new(html, :with_html_string => true, :adapter => adapter)
68
+ premailer.to_inline_css
69
+
70
+ h = premailer.processed_doc.at('head')
71
+ assert_nil h['style']
72
+
73
+ t = premailer.processed_doc.at('title')
74
+ assert_nil t['style']
75
+ end
76
+ end
77
+
78
+ def test_multiple_identical_ids
79
+ html = <<-END_HTML
80
+ <html>
81
+ <head>
82
+ <style type="text/css"> #the_id { color: red; } </style>
83
+ </head>
84
+ <body>
85
+ <p id="the_id">Test</p>
86
+ <p id="the_id">Test</p>
87
+ </body>
88
+ </html>
89
+ END_HTML
90
+
91
+ premailer = Premailer.new(html, :with_html_string => true)
92
+ premailer.to_inline_css
93
+ premailer.processed_doc.search('p').each do |el|
94
+ assert_match /red/i, el['style']
95
+ end
96
+ end
97
+
98
+ def test_preserving_styles
99
+ html = <<END_HTML
100
+ <html>
101
+ <head>
102
+ <link rel="stylesheet" href="#"/>
103
+ <style type="text/css"> a:hover { color: red; } </style>
104
+ </head>
105
+ <body>
106
+ <p><a>Test</a></p>
107
+ </body>
108
+ </html>
109
+ END_HTML
110
+ [:nokogiri, :hpricot].each do |adapter|
111
+ premailer = Premailer.new(html, :with_html_string => true, :preserve_styles => true, :adapter => adapter)
112
+ premailer.to_inline_css
113
+ assert_equal 1, premailer.processed_doc.search('head link').length
114
+ assert_equal 1, premailer.processed_doc.search('head style').length
115
+
116
+ premailer = Premailer.new(html, :with_html_string => true, :preserve_styles => false, :adapter => adapter)
117
+ premailer.to_inline_css
118
+ assert_nil premailer.processed_doc.at('head link')
119
+
120
+ # should be preserved as unmergeable
121
+ assert_match /red !important/i, premailer.processed_doc.at('body style').inner_html
122
+ end
123
+ end
124
+
125
+ def test_unmergable_rules
126
+ html = <<END_HTML
127
+ <html> <head> <style type="text/css"> a { color:blue; } a:hover { color: red; } </style> </head>
128
+ <p><a>Test</a></p>
129
+ </body> </html>
130
+ END_HTML
131
+
132
+ premailer = Premailer.new(html, :with_html_string => true, :verbose => true)
133
+ premailer.to_inline_css
134
+ assert_match /a\:hover[\s]*\{[\s]*color\:[\s]*red[\s]*!important;[\s]*\}/i, premailer.processed_doc.at('body style').inner_html
135
+ end
136
+
137
+ def test_unmergable_rules_with_no_body
138
+ html = <<END_HTML
139
+ <html>
140
+ <style type="text/css"> a:hover { color: red; } </style>
141
+ <p><a>Test</a></p>
142
+ </html>
143
+ END_HTML
144
+
145
+ premailer = Premailer.new(html, :with_html_string => true)
146
+ assert_nothing_raised do
147
+ premailer.to_inline_css
148
+ end
149
+ assert_match /red !important/i, premailer.processed_doc.at('style').inner_html
150
+ end
151
+
152
+ # in response to https://github.com/alexdunae/premailer/issues#issue/7
153
+ def test_ignoring_link_pseudo_selectors
154
+ html = <<END_HTML
155
+ <html>
156
+ <style type="text/css"> td a:link.top_links { color: red; } </style>
157
+ <body>
158
+ <td><a class="top_links">Test</a></td>
159
+ </body>
160
+ </html>
161
+ END_HTML
162
+
163
+ premailer = Premailer.new(html, :with_html_string => true)
164
+ assert_nothing_raised do
165
+ premailer.to_inline_css
166
+ end
167
+ assert_match /color: red/, premailer.processed_doc.at('a').attributes['style'].to_s
168
+ end
169
+
170
+ # in response to https://github.com/alexdunae/premailer/issues#issue/7
171
+ def test_parsing_bad_markup_around_tables
172
+ html = <<END_HTML
173
+ <html>
174
+ <style type="text/css">
175
+ .style3 { font-size: xx-large; }
176
+ .style5 { background-color: #000080; }
177
+ </style>
178
+ <tr>
179
+ <td valign="top" class="style3">
180
+ <!-- MSCellType="ContentHead" -->
181
+ <strong>PROMOCION CURSOS PRESENCIALES</strong></td>
182
+ <strong>
183
+ <td valign="top" style="height: 125px" class="style5">
184
+ <!-- MSCellType="DecArea" -->
185
+ <img alt="" src="../../images/CertisegGold.GIF" width="608" height="87" /></td>
186
+ </tr>
187
+ END_HTML
188
+
189
+ premailer = Premailer.new(html, :with_html_string => true)
190
+ premailer.to_inline_css
191
+ assert_match /font-size: xx-large/, premailer.processed_doc.search('.style3').first.attributes['style'].to_s
192
+ assert_match /background-color: #000080/, premailer.processed_doc.search('.style5').first.attributes['style'].to_s
193
+ end
194
+
195
+ # in response to https://github.com/alexdunae/premailer/issues/56
196
+ def test_inline_important
197
+ html = <<END_HTML
198
+ <html>
199
+ <style type="text/css">
200
+ p { color: red !important; }
201
+ </style>
202
+ <body>
203
+ <p style='color: green !important;'>test</p></div>
204
+ </body>
205
+ </html>
206
+ END_HTML
207
+
208
+ premailer = Premailer.new(html, :with_html_string => true, :adapter => :nokogiri)
209
+ premailer.to_inline_css
210
+ assert_equal 'color: green !important;', premailer.processed_doc.search('p').first.attributes['style'].to_s
211
+ end
212
+
213
+ # in response to https://github.com/alexdunae/premailer/issues/28
214
+ def test_handling_shorthand_auto_properties
215
+ html = <<END_HTML
216
+ <html>
217
+ <style type="text/css">
218
+ #page { margin: 0; margin-left: auto; margin-right: auto; }
219
+ p { border: 1px solid black; border-right: none; }
220
+
221
+ </style>
222
+ <body>
223
+ <div id='page'><p>test</p></div>
224
+ </body>
225
+ </html>
226
+ END_HTML
227
+
228
+ premailer = Premailer.new(html, :with_html_string => true)
229
+ premailer.to_inline_css
230
+ assert_match /margin: 0 auto;/, premailer.processed_doc.search('#page').first.attributes['style'].to_s
231
+ assert_match /border-style: solid none solid solid;/, premailer.processed_doc.search('p').first.attributes['style'].to_s
232
+ end
233
+ end
@@ -0,0 +1,257 @@
1
+ # encoding: UTF-8
2
+ require File.expand_path(File.dirname(__FILE__)) + '/helper'
3
+
4
+ class TestPremailer < Test::Unit::TestCase
5
+ include WEBrick
6
+
7
+ def setup
8
+ # from http://nullref.se/blog/2006/5/17/testing-with-webrick
9
+ @uri_base = "http://localhost:12000"
10
+ www_root = File.expand_path(File.dirname(__FILE__)) + '/files/'
11
+
12
+ @server_thread = Thread.new do
13
+ s = WEBrick::HTTPServer.new(:Port => 12000, :DocumentRoot => www_root, :Logger => Log.new(nil, BasicLog::ERROR), :AccessLog => [])
14
+ port = s.config[:Port]
15
+ begin
16
+ s.start
17
+ ensure
18
+ s.shutdown
19
+ end
20
+ end
21
+ end
22
+
23
+ def test_special_characters_nokogiri
24
+ html = '<p>cédille c&eacute; & garçon gar&#231;on à &agrave; &nbsp; &amp; &copy;</p>'
25
+ premailer = Premailer.new(html, :with_html_string => true, :adapter => :nokogiri)
26
+ premailer.to_inline_css
27
+ assert_equal 'c&eacute;dille c&eacute; &amp; gar&ccedil;on gar&ccedil;on &agrave; &agrave; &nbsp; &amp; &copy;', premailer.processed_doc.at('p').inner_html
28
+ end
29
+
30
+ def test_special_characters_nokogiri_remote
31
+ remote_setup('chars.html', :adapter => :nokogiri)
32
+ @premailer.to_inline_css
33
+ assert_equal 'c&eacute;dille c&eacute; &amp; gar&ccedil;on gar&ccedil;on &agrave; &agrave; &nbsp; &amp; &copy;', @premailer.processed_doc.at('p').inner_html
34
+ end
35
+
36
+ #def test_cyrillic_nokogiri_remote
37
+ # if RUBY_VERSION =~ /1.9/
38
+ # remote_setup('iso-8859-5.html', :adapter => :nokogiri) #, :encoding => 'iso-8859-5')
39
+ # @premailer.to_inline_css
40
+ # assert_equal Encoding.find('ISO-8859-5'), @premailer.processed_doc.at('p').inner_html.encoding
41
+ # end
42
+ #end
43
+
44
+ # TODO: this passes when run from rake but not when run from:
45
+ # ruby -Itest test/test_premailer.rb -n test_special_characters_hpricot
46
+ def test_special_characters_hpricot
47
+ html = '<p>cédille c&eacute; & garçon gar&#231;on à &agrave; &nbsp; &amp;</p>'
48
+ premailer = Premailer.new(html, :with_html_string => true, :adapter => :hpricot)
49
+ premailer.to_inline_css
50
+ assert_equal 'c&eacute;dille c&eacute; &amp; gar&ccedil;on gar&ccedil;on &agrave; &agrave; &nbsp; &amp;', premailer.processed_doc.at('p').inner_html
51
+ end
52
+
53
+
54
+ def test_detecting_html
55
+ [:nokogiri, :hpricot].each do |adapter|
56
+ remote_setup('base.html', :adapter => adapter)
57
+ assert !@premailer.is_xhtml?
58
+ end
59
+ end
60
+
61
+ def test_detecting_xhtml
62
+ [:nokogiri, :hpricot].each do |adapter|
63
+ remote_setup('xhtml.html', :adapter => adapter)
64
+ assert @premailer.is_xhtml?
65
+ end
66
+ end
67
+
68
+ def test_self_closing_xhtml_tags
69
+ [:nokogiri, :hpricot].each do |adapter|
70
+ remote_setup('xhtml.html', :adapter => adapter)
71
+ assert_match /<br[\s]*\/>/, @premailer.to_s
72
+ assert_match /<br[\s]*\/>/, @premailer.to_inline_css
73
+ end
74
+ end
75
+
76
+ def test_non_self_closing_html_tags
77
+ [:nokogiri, :hpricot].each do |adapter|
78
+ remote_setup('html4.html', :adapter => adapter)
79
+ assert_match /<br>/, @premailer.to_s
80
+ assert_match /<br>/, @premailer.to_inline_css
81
+ end
82
+ end
83
+
84
+ def test_mailtos_with_query_strings
85
+ html = <<END_HTML
86
+ <html>
87
+ <a href="mailto:info@example.com?subject=Programmübersicht&amp;body=Lorem ipsum dolor sit amet.">Test</a>
88
+ </html>
89
+ END_HTML
90
+
91
+ qs = 'testing=123'
92
+
93
+ [:nokogiri, :hpricot].each do |adapter|
94
+ premailer = Premailer.new(html, :with_html_string => true, :link_query_string => qs, :adapter => adapter)
95
+ premailer.to_inline_css
96
+ assert_no_match /testing=123/, premailer.processed_doc.search('a').first.attributes['href'].to_s
97
+ end
98
+ end
99
+
100
+ def test_escaping_strings
101
+ local_setup
102
+
103
+ str = %q{url("/images/test.png");}
104
+ assert_equal("url(\'/images/test.png\');", Premailer.escape_string(str))
105
+ end
106
+
107
+ def test_importing_local_css
108
+ [:nokogiri, :hpricot].each do |adapter|
109
+ local_setup('base.html', :adapter => adapter)
110
+
111
+ # noimport.css (print stylesheet) sets body { background } to red
112
+ assert_no_match /red/, @doc.at('body').attributes['style'].to_s
113
+
114
+ # import.css sets .hide to { display: none }
115
+ assert_match /display: none/, @doc.at('#hide01').attributes['style'].to_s
116
+ end
117
+ end
118
+
119
+ def test_importing_remote_css
120
+ [:nokogiri, :hpricot].each do |adapter|
121
+ remote_setup('base.html', :adapter => adapter)
122
+
123
+ # noimport.css (print stylesheet) sets body { background } to red
124
+ assert_no_match /red/, @doc.at('body')['style']
125
+
126
+ # import.css sets .hide to { display: none }
127
+ assert_match /display: none/, @doc.at('#hide01')['style']
128
+ end
129
+ end
130
+
131
+ def test_importing_css_as_string
132
+ files_base = File.expand_path(File.dirname(__FILE__)) + '/files/'
133
+
134
+ css_string = IO.read(File.join(files_base, 'import.css'))
135
+
136
+ [:nokogiri, :hpricot].each do |adapter|
137
+ premailer = Premailer.new(File.join(files_base, 'no_css.html'), {:css_string => css_string, :adapter => adapter})
138
+ premailer.to_inline_css
139
+ @doc = premailer.processed_doc
140
+
141
+ # import.css sets .hide to { display: none }
142
+ assert_match /display: none/, @doc.at('#hide01')['style']
143
+ end
144
+ end
145
+
146
+ def test_local_remote_check
147
+ assert Premailer.local_data?( StringIO.new('a') )
148
+ assert Premailer.local_data?( '/path/' )
149
+ assert !Premailer.local_data?( 'http://example.com/path/' )
150
+
151
+ # the old way is deprecated but should still work
152
+ premailer = Premailer.new( StringIO.new('a') )
153
+ assert premailer.local_uri?( '/path/' )
154
+ end
155
+
156
+ def test_initialize_can_accept_io_object
157
+ [:nokogiri, :hpricot].each do |adapter|
158
+ io = StringIO.new('hi mom')
159
+ premailer = Premailer.new(io, :adapter => adapter)
160
+ assert_match /hi mom/, premailer.to_inline_css
161
+ end
162
+ end
163
+
164
+ def test_initialize_can_accept_html_string
165
+ [:nokogiri, :hpricot].each do |adapter|
166
+ premailer = Premailer.new('<p>test</p>', :with_html_string => true, :adapter => adapter)
167
+ assert_match /test/, premailer.to_inline_css
168
+ end
169
+ end
170
+
171
+ def test_remove_ids
172
+ html = <<END_HTML
173
+ <html> <head> <style type="text/css"> #remove { color:blue; } </style> </head>
174
+ <body>
175
+ <p id="remove"><a href="#keep">Test</a></p>
176
+ <p id="keep">Test</p>
177
+ </body> </html>
178
+ END_HTML
179
+
180
+ [:nokogiri, :hpricot].each do |adapter|
181
+ pm = Premailer.new(html, :with_html_string => true, :remove_ids => true, :adapter => adapter)
182
+ pm.to_inline_css
183
+ doc = pm.processed_doc
184
+ assert_nil doc.at('#remove')
185
+ assert_nil doc.at('#keep')
186
+ hashed_id = doc.at('a')['href'][1..-1]
187
+ assert_not_nil doc.at("\##{hashed_id}")
188
+ end
189
+ end
190
+
191
+ def test_carriage_returns_as_entities
192
+ html = <<-html
193
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
194
+ <html>
195
+ <body>\n\r<p>test</p>\n\r<p>test</p>
196
+ </body></html>
197
+ html
198
+
199
+ [:nokogiri, :hpricot].each do |adapter|
200
+ pm = Premailer.new(html, :with_html_string => true, :adapter => adapter)
201
+ assert_match /\r/, pm.to_inline_css
202
+ end
203
+ end
204
+
205
+
206
+ def test_advanced_selectors
207
+ remote_setup('base.html', :adapter => :nokogiri)
208
+ assert_match /italic/, @doc.at('h2 + h3')['style']
209
+ assert_match /italic/, @doc.at('p[attr~=quote]')['style']
210
+ assert_match /italic/, @doc.at('ul li:first-of-type')['style']
211
+
212
+ remote_setup('base.html', :adapter => :hpricot)
213
+ assert_match /italic/, @doc.at('p[@attr~="quote"]')['style']
214
+ assert_match /italic/, @doc.at('ul li:first-of-type')['style']
215
+ end
216
+
217
+ def test_premailer_related_attributes
218
+ html = <<END_HTML
219
+ <html> <head> <style>table { -premailer-width: 500; } td { -premailer-height: 20}; </style>
220
+ <body>
221
+ <table> <tr> <td> Test </td> </tr> </table>
222
+ </body> </html>
223
+ END_HTML
224
+
225
+ [:nokogiri, :hpricot].each do |adapter|
226
+ pm = Premailer.new(html, :with_html_string => true, :adapter => adapter)
227
+ pm.to_inline_css
228
+ doc = pm.processed_doc
229
+ assert_equal '500', doc.at('table')['width']
230
+ assert_equal '20', doc.at('td')['height']
231
+ end
232
+ end
233
+
234
+
235
+ protected
236
+ def local_setup(f = 'base.html', opts = {})
237
+ base_file = File.expand_path(File.dirname(__FILE__)) + '/files/' + f
238
+ premailer = Premailer.new(base_file, opts)
239
+ premailer.to_inline_css
240
+ @doc = premailer.processed_doc
241
+ end
242
+
243
+ def remote_setup(f = 'base.html', opts = {})
244
+ # increment the port number for testing multiple adapters
245
+ @premailer = Premailer.new(@uri_base + "/#{f}", opts)
246
+ @premailer.to_inline_css
247
+ @doc = @premailer.processed_doc
248
+ end
249
+
250
+ def teardown
251
+ if @server_thread
252
+ @server_thread.kill
253
+ @server_thread.join(5)
254
+ @server_thread = nil
255
+ end
256
+ end
257
+ end