mechanize 2.7.3 → 2.8.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of mechanize might be problematic. Click here for more details.

Files changed (137) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci-test.yml +45 -0
  3. data/.gitignore +15 -0
  4. data/.yardopts +8 -0
  5. data/{CHANGELOG.rdoc → CHANGELOG.md} +149 -62
  6. data/EXAMPLES.rdoc +2 -25
  7. data/Gemfile +3 -0
  8. data/{LICENSE.rdoc → LICENSE.txt} +4 -0
  9. data/README.md +79 -0
  10. data/Rakefile +36 -37
  11. data/examples/{rubyforge.rb → rubygems.rb} +7 -6
  12. data/lib/mechanize.rb +75 -33
  13. data/lib/mechanize/chunked_termination_error.rb +1 -0
  14. data/lib/mechanize/content_type_error.rb +1 -0
  15. data/lib/mechanize/cookie.rb +1 -13
  16. data/lib/mechanize/cookie_jar.rb +4 -12
  17. data/lib/mechanize/directory_saver.rb +15 -2
  18. data/lib/mechanize/download.rb +2 -1
  19. data/lib/mechanize/element_matcher.rb +29 -14
  20. data/lib/mechanize/element_not_found_error.rb +1 -0
  21. data/lib/mechanize/file.rb +2 -1
  22. data/lib/mechanize/file_connection.rb +5 -3
  23. data/lib/mechanize/file_request.rb +1 -0
  24. data/lib/mechanize/file_response.rb +5 -4
  25. data/lib/mechanize/file_saver.rb +1 -0
  26. data/lib/mechanize/form.rb +119 -46
  27. data/lib/mechanize/form/button.rb +1 -0
  28. data/lib/mechanize/form/check_box.rb +1 -0
  29. data/lib/mechanize/form/field.rb +47 -0
  30. data/lib/mechanize/form/file_upload.rb +1 -0
  31. data/lib/mechanize/form/hidden.rb +1 -0
  32. data/lib/mechanize/form/image_button.rb +1 -0
  33. data/lib/mechanize/form/keygen.rb +1 -0
  34. data/lib/mechanize/form/multi_select_list.rb +8 -14
  35. data/lib/mechanize/form/option.rb +3 -1
  36. data/lib/mechanize/form/radio_button.rb +1 -0
  37. data/lib/mechanize/form/reset.rb +1 -0
  38. data/lib/mechanize/form/select_list.rb +1 -0
  39. data/lib/mechanize/form/submit.rb +1 -0
  40. data/lib/mechanize/form/text.rb +1 -0
  41. data/lib/mechanize/form/textarea.rb +1 -0
  42. data/lib/mechanize/headers.rb +1 -0
  43. data/lib/mechanize/history.rb +2 -1
  44. data/lib/mechanize/http.rb +1 -0
  45. data/lib/mechanize/http/agent.rb +115 -64
  46. data/lib/mechanize/http/auth_challenge.rb +1 -0
  47. data/lib/mechanize/http/auth_realm.rb +2 -1
  48. data/lib/mechanize/http/auth_store.rb +3 -0
  49. data/lib/mechanize/http/content_disposition_parser.rb +18 -3
  50. data/lib/mechanize/http/www_authenticate_parser.rb +5 -5
  51. data/lib/mechanize/image.rb +1 -0
  52. data/lib/mechanize/page.rb +166 -55
  53. data/lib/mechanize/page/base.rb +1 -0
  54. data/lib/mechanize/page/frame.rb +4 -1
  55. data/lib/mechanize/page/image.rb +3 -0
  56. data/lib/mechanize/page/label.rb +1 -0
  57. data/lib/mechanize/page/link.rb +13 -1
  58. data/lib/mechanize/page/meta_refresh.rb +1 -0
  59. data/lib/mechanize/parser.rb +4 -3
  60. data/lib/mechanize/pluggable_parsers.rb +14 -1
  61. data/lib/mechanize/prependable.rb +1 -0
  62. data/lib/mechanize/redirect_limit_reached_error.rb +1 -0
  63. data/lib/mechanize/redirect_not_get_or_head_error.rb +1 -0
  64. data/lib/mechanize/response_code_error.rb +2 -1
  65. data/lib/mechanize/response_read_error.rb +1 -0
  66. data/lib/mechanize/robots_disallowed_error.rb +1 -0
  67. data/lib/mechanize/test_case.rb +39 -29
  68. data/lib/mechanize/test_case/bad_chunking_servlet.rb +1 -0
  69. data/lib/mechanize/test_case/basic_auth_servlet.rb +1 -0
  70. data/lib/mechanize/test_case/content_type_servlet.rb +1 -0
  71. data/lib/mechanize/test_case/digest_auth_servlet.rb +1 -0
  72. data/lib/mechanize/test_case/file_upload_servlet.rb +1 -0
  73. data/lib/mechanize/test_case/form_servlet.rb +1 -0
  74. data/lib/mechanize/test_case/gzip_servlet.rb +4 -3
  75. data/lib/mechanize/test_case/header_servlet.rb +1 -0
  76. data/lib/mechanize/test_case/http_refresh_servlet.rb +2 -2
  77. data/lib/mechanize/test_case/infinite_redirect_servlet.rb +1 -0
  78. data/lib/mechanize/test_case/infinite_refresh_servlet.rb +2 -2
  79. data/lib/mechanize/test_case/many_cookies_as_string_servlet.rb +1 -0
  80. data/lib/mechanize/test_case/many_cookies_servlet.rb +1 -0
  81. data/lib/mechanize/test_case/modified_since_servlet.rb +1 -0
  82. data/lib/mechanize/test_case/ntlm_servlet.rb +1 -0
  83. data/lib/mechanize/test_case/one_cookie_no_spaces_servlet.rb +1 -0
  84. data/lib/mechanize/test_case/one_cookie_servlet.rb +1 -0
  85. data/lib/mechanize/test_case/quoted_value_cookie_servlet.rb +1 -0
  86. data/lib/mechanize/test_case/redirect_servlet.rb +1 -0
  87. data/lib/mechanize/test_case/referer_servlet.rb +1 -0
  88. data/lib/mechanize/test_case/refresh_with_empty_url.rb +1 -0
  89. data/lib/mechanize/test_case/refresh_without_url.rb +1 -0
  90. data/lib/mechanize/test_case/response_code_servlet.rb +1 -0
  91. data/lib/mechanize/test_case/robots_txt_servlet.rb +15 -0
  92. data/lib/mechanize/test_case/send_cookies_servlet.rb +1 -0
  93. data/lib/mechanize/test_case/server.rb +1 -0
  94. data/lib/mechanize/test_case/servlets.rb +4 -0
  95. data/lib/mechanize/test_case/verb_servlet.rb +5 -6
  96. data/lib/mechanize/unauthorized_error.rb +2 -1
  97. data/lib/mechanize/unsupported_scheme_error.rb +5 -2
  98. data/lib/mechanize/util.rb +90 -43
  99. data/lib/mechanize/version.rb +4 -0
  100. data/lib/mechanize/xml_file.rb +1 -0
  101. data/mechanize.gemspec +69 -0
  102. data/test/htdocs/dir with spaces/foo.html +1 -0
  103. data/test/htdocs/find_link.html +1 -4
  104. data/test/htdocs/tc_links.html +1 -1
  105. data/test/test_mechanize.rb +111 -55
  106. data/test/test_mechanize_cookie.rb +75 -60
  107. data/test/test_mechanize_cookie_jar.rb +112 -59
  108. data/test/test_mechanize_download.rb +13 -1
  109. data/test/test_mechanize_file.rb +10 -0
  110. data/test/test_mechanize_file_connection.rb +21 -3
  111. data/test/test_mechanize_file_response.rb +26 -2
  112. data/test/test_mechanize_form.rb +46 -11
  113. data/test/test_mechanize_form_check_box.rb +10 -0
  114. data/test/test_mechanize_form_encoding.rb +3 -8
  115. data/test/test_mechanize_form_keygen.rb +1 -0
  116. data/test/test_mechanize_form_multi_select_list.rb +5 -1
  117. data/test/test_mechanize_http_agent.rb +175 -18
  118. data/test/test_mechanize_http_auth_challenge.rb +14 -0
  119. data/test/test_mechanize_http_auth_realm.rb +7 -1
  120. data/test/test_mechanize_http_auth_store.rb +37 -0
  121. data/test/test_mechanize_http_content_disposition_parser.rb +35 -1
  122. data/test/test_mechanize_http_www_authenticate_parser.rb +24 -0
  123. data/test/test_mechanize_link.rb +60 -4
  124. data/test/test_mechanize_page.rb +82 -7
  125. data/test/test_mechanize_page_encoding.rb +2 -3
  126. data/test/test_mechanize_page_image.rb +1 -1
  127. data/test/test_mechanize_page_link.rb +20 -5
  128. data/test/test_mechanize_page_meta_refresh.rb +1 -1
  129. data/test/test_mechanize_parser.rb +12 -2
  130. data/test/test_mechanize_util.rb +46 -11
  131. metadata +198 -99
  132. data/.gemtest +0 -0
  133. data/.travis.yml +0 -26
  134. data/Manifest.txt +0 -205
  135. data/README.rdoc +0 -83
  136. data/lib/mechanize/monkey_patch.rb +0 -17
  137. data/test/htdocs/robots.txt +0 -2
@@ -25,6 +25,14 @@ class TestMechanizeHttpAuthChallenge < Mechanize::TestCase
25
25
  assert_equal expected, @challenge.realm(@uri + '/foo')
26
26
  end
27
27
 
28
+ def test_realm_digest_case
29
+ challenge = @AC.new 'Digest', { 'realm' => 'R' }, 'Digest realm=R'
30
+
31
+ expected = @AR.new 'Digest', @uri, 'R'
32
+
33
+ assert_equal expected, challenge.realm(@uri + '/foo')
34
+ end
35
+
28
36
  def test_realm_unknown
29
37
  @challenge.scheme = 'Unknown'
30
38
 
@@ -39,6 +47,12 @@ class TestMechanizeHttpAuthChallenge < Mechanize::TestCase
39
47
  assert_equal 'r', @challenge.realm_name
40
48
  end
41
49
 
50
+ def test_realm_name_case
51
+ challenge = @AC.new 'Digest', { 'realm' => 'R' }, 'Digest realm=R'
52
+
53
+ assert_equal 'R', challenge.realm_name
54
+ end
55
+
42
56
  def test_realm_name_ntlm
43
57
  challenge = @AC.new 'Negotiate, NTLM'
44
58
 
@@ -14,7 +14,10 @@ class TestMechanizeHttpAuthRealm < Mechanize::TestCase
14
14
  assert_equal 'r', @realm.realm
15
15
 
16
16
  realm = @AR.new 'Digest', @uri, 'R'
17
- assert_equal 'r', realm.realm
17
+ refute_equal 'r', realm.realm
18
+
19
+ realm = @AR.new 'Digest', @uri, 'R'
20
+ assert_equal 'R', realm.realm
18
21
 
19
22
  realm = @AR.new 'Digest', @uri, nil
20
23
  assert_nil realm.realm
@@ -30,6 +33,9 @@ class TestMechanizeHttpAuthRealm < Mechanize::TestCase
30
33
  other = @AR.new 'Digest', URI('http://other.example/'), 'r'
31
34
  refute_equal @realm, other
32
35
 
36
+ other = @AR.new 'Digest', @uri, 'R'
37
+ refute_equal @realm, other
38
+
33
39
  other = @AR.new 'Digest', @uri, 's'
34
40
  refute_equal @realm, other
35
41
  end
@@ -57,6 +57,20 @@ class TestMechanizeHttpAuthStore < Mechanize::TestCase
57
57
  assert_equal expected, @store.auth_accounts
58
58
  end
59
59
 
60
+ def test_add_auth_realm_case
61
+ @store.add_auth @uri, 'user1', 'pass', 'realm'
62
+ @store.add_auth @uri, 'user2', 'pass', 'Realm'
63
+
64
+ expected = {
65
+ @uri => {
66
+ 'realm' => ['user1', 'pass', nil],
67
+ 'Realm' => ['user2', 'pass', nil],
68
+ }
69
+ }
70
+
71
+ assert_equal expected, @store.auth_accounts
72
+ end
73
+
60
74
  def test_add_auth_string
61
75
  @store.add_auth "#{@uri}/path", 'user', 'pass'
62
76
 
@@ -143,6 +157,14 @@ class TestMechanizeHttpAuthStore < Mechanize::TestCase
143
157
  assert_equal ['user1', 'pass', nil], @store.credentials_for(@uri, 'other')
144
158
  end
145
159
 
160
+ def test_credentials_for_realm_case
161
+ @store.add_auth @uri, 'user1', 'pass', 'realm'
162
+ @store.add_auth @uri, 'user2', 'pass', 'Realm'
163
+
164
+ assert_equal ['user1', 'pass', nil], @store.credentials_for(@uri, 'realm')
165
+ assert_equal ['user2', 'pass', nil], @store.credentials_for(@uri, 'Realm')
166
+ end
167
+
146
168
  def test_credentials_for_path
147
169
  @store.add_auth @uri, 'user', 'pass', 'realm'
148
170
 
@@ -183,6 +205,21 @@ class TestMechanizeHttpAuthStore < Mechanize::TestCase
183
205
  assert_equal expected, @store.auth_accounts
184
206
  end
185
207
 
208
+ def test_remove_auth_realm_case
209
+ @store.add_auth @uri, 'user1', 'pass', 'realm'
210
+ @store.add_auth @uri, 'user2', 'pass', 'Realm'
211
+
212
+ @store.remove_auth @uri, 'Realm'
213
+
214
+ expected = {
215
+ @uri => {
216
+ 'realm' => ['user1', 'pass', nil]
217
+ }
218
+ }
219
+
220
+ assert_equal expected, @store.auth_accounts
221
+ end
222
+
186
223
  def test_remove_auth_string
187
224
  @store.add_auth @uri, 'user1', 'pass'
188
225
 
@@ -30,6 +30,33 @@ class TestMechanizeHttpContentDispositionParser < Mechanize::TestCase
30
30
  assert_equal expected, content_disposition.parameters
31
31
  end
32
32
 
33
+ def test_parse_date_iso8601_fallback
34
+ now = Time.at Time.now.to_i
35
+
36
+ content_disposition = @parser.parse \
37
+ 'attachment;' \
38
+ 'filename=value;' \
39
+ "creation-date=\"#{now.iso8601}\";" \
40
+ "modification-date=\"#{(now + 1).iso8601}\""
41
+
42
+ assert_equal 'attachment', content_disposition.type
43
+ assert_equal 'value', content_disposition.filename
44
+ assert_equal now, content_disposition.creation_date
45
+ assert_equal((now + 1), content_disposition.modification_date)
46
+ end
47
+
48
+ def test_parse_date_invalid
49
+ now = Time.at Time.now.to_i
50
+
51
+ content_disposition = @parser.parse \
52
+ 'attachment;' \
53
+ 'filename=value;' \
54
+ "creation-date=\"#{now.to_s}\";" \
55
+ "modification-date=\"#{(now + 1).to_s}\""
56
+
57
+ assert_nil content_disposition
58
+ end
59
+
33
60
  def test_parse_header
34
61
  content_disposition = @parser.parse \
35
62
  'content-disposition: attachment;filename=value', true
@@ -119,7 +146,7 @@ class TestMechanizeHttpContentDispositionParser < Mechanize::TestCase
119
146
 
120
147
  assert_equal 'end "', string
121
148
  end
122
-
149
+
123
150
  def test_parse_uppercase
124
151
  content_disposition = @parser.parse \
125
152
  'content-disposition: attachment; Filename=value', true
@@ -128,5 +155,12 @@ class TestMechanizeHttpContentDispositionParser < Mechanize::TestCase
128
155
  assert_equal 'value', content_disposition.filename
129
156
  end
130
157
 
158
+ def test_parse_filename_starting_with_escaped_quote
159
+ content_disposition = @parser.parse \
160
+ 'content-disposition: attachment; Filename="\"value\""', true
161
+
162
+ assert_equal '"value"', content_disposition.filename
163
+ end
164
+
131
165
  end
132
166
 
@@ -109,6 +109,14 @@ class TestMechanizeHttpWwwAuthenticateParser < Mechanize::TestCase
109
109
  assert_equal expected, @parser.parse('Basic ReAlM=foo')
110
110
  end
111
111
 
112
+ def test_parse_realm_value_case
113
+ expected = [
114
+ challenge('Basic', { 'realm' => 'Foo' }, 'Basic realm=Foo'),
115
+ ]
116
+
117
+ assert_equal expected, @parser.parse('Basic realm=Foo')
118
+ end
119
+
112
120
  def test_parse_scheme_uppercase
113
121
  expected = [
114
122
  challenge('Basic', { 'realm' => 'foo' }, 'BaSiC realm=foo'),
@@ -117,6 +125,22 @@ class TestMechanizeHttpWwwAuthenticateParser < Mechanize::TestCase
117
125
  assert_equal expected, @parser.parse('BaSiC realm=foo')
118
126
  end
119
127
 
128
+ def test_parse_bad_whitespace_around_auth_param
129
+ expected = [
130
+ challenge('Basic', { 'realm' => 'foo' }, 'Basic realm = "foo"'),
131
+ ]
132
+
133
+ assert_equal expected, @parser.parse('Basic realm = "foo"')
134
+ end
135
+
136
+ def test_parse_bad_single_quote
137
+ expected = [
138
+ challenge('Basic', { 'realm' => "'foo" }, "Basic realm='foo"),
139
+ ]
140
+
141
+ assert_equal expected, @parser.parse("Basic realm='foo bar', qop='baz'")
142
+ end
143
+
120
144
  def test_quoted_string
121
145
  @parser.scanner = StringScanner.new '"text"'
122
146
 
@@ -2,6 +2,25 @@ require 'mechanize/test_case'
2
2
 
3
3
  class TestMechanizeLink < Mechanize::TestCase
4
4
 
5
+ def test_search
6
+ page = @mech.get("http://localhost/find_link.html")
7
+ link = page.link_with(text: "Form Test")
8
+
9
+ assert_equal('Form Test', link.text)
10
+
11
+ link_with_search = page.link_with(search: "//*[text()='Form Test']")
12
+ assert_equal(link, link_with_search)
13
+
14
+ link_with_xpath = page.link_with(xpath: "//*[text()='Form Test']")
15
+ assert_equal(link, link_with_xpath)
16
+
17
+ link_with_css = page.link_with(css: ".formtest")
18
+ assert_equal(link, link_with_css)
19
+
20
+ link_with_class = page.link_with(class: "formtest")
21
+ assert_equal(link, link_with_class)
22
+ end
23
+
5
24
  def test_click
6
25
  page = @mech.get("http://localhost/frame_test.html")
7
26
  link = page.link_with(:text => "Form Test")
@@ -10,7 +29,7 @@ class TestMechanizeLink < Mechanize::TestCase
10
29
  page = link.click
11
30
  assert_equal("http://localhost/form_test.html",
12
31
  @mech.history.last.uri.to_s)
13
- end
32
+ end unless RUBY_ENGINE == 'jruby' # NekoHTML does not parse body of NOFRAMES
14
33
 
15
34
  def test_click_bang
16
35
  page = @mech.get("http://localhost/frame_test.html")
@@ -20,7 +39,7 @@ class TestMechanizeLink < Mechanize::TestCase
20
39
  page = link.click
21
40
  assert_equal("http://localhost/form_test.html",
22
41
  @mech.history.last.uri.to_s)
23
- end
42
+ end unless RUBY_ENGINE == 'jruby' # NekoHTML does not parse body of NOFRAMES
24
43
 
25
44
  def test_click_base
26
45
  page = @mech.get("http://google.com/tc_base_link.html")
@@ -32,7 +51,13 @@ class TestMechanizeLink < Mechanize::TestCase
32
51
  page = @mech.get("http://google.com/tc_links.html")
33
52
  link = page.link_with(:text => 'javascript link')
34
53
  assert_raises Mechanize::UnsupportedSchemeError do
35
- link.click
54
+ begin
55
+ link.click
56
+ rescue Mechanize::UnsupportedSchemeError => error
57
+ assert_equal 'javascript', error.scheme
58
+ assert_equal "javascript:new_page('1')", error.uri.to_s
59
+ raise
60
+ end
36
61
  end
37
62
 
38
63
  @mech.scheme_handlers['javascript'] = lambda { |my_link, my_page|
@@ -97,7 +122,7 @@ class TestMechanizeLink < Mechanize::TestCase
97
122
  page = page.link_with(:text => 'just the query string').click
98
123
  assert_equal('http://localhost/relative/tc_relative_links.html?a=b',
99
124
  page.uri.to_s)
100
- end
125
+ end unless RUBY_ENGINE == 'jruby' # NekoHTML does not parse IFRAME
101
126
 
102
127
  def test_uri_weird
103
128
  doc = Nokogiri::HTML::Document.new
@@ -110,5 +135,36 @@ class TestMechanizeLink < Mechanize::TestCase
110
135
  assert_equal 'http://foo.bar/%20baz', link.uri.to_s
111
136
  end
112
137
 
138
+ def test_uri_weird_with_fragment
139
+ doc = Nokogiri::HTML::Document.new
140
+
141
+ node = Nokogiri::XML::Node.new('foo', doc)
142
+ node['href'] = 'http://foo.bar/ baz#уважение'
143
+
144
+ link = Mechanize::Page::Link.new(node, nil, nil)
145
+
146
+ assert_equal '%D1%83%D0%B2%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5', link.uri.fragment
147
+ end
148
+
149
+ def test_bad_uri_raise_compatible_exception
150
+ doc = Nokogiri::HTML::Document.new
151
+
152
+ node = Nokogiri::XML::Node.new('foo', doc)
153
+ node['href'] = 'http://http:foo.bar/ baz'
154
+
155
+ link = Mechanize::Page::Link.new(node, nil, nil)
156
+
157
+ assert_raises URI::InvalidURIError do
158
+ link.uri
159
+ end
160
+ end
161
+
162
+ def test_resolving_full_uri
163
+ page = @mech.get("http://localhost/frame_test.html")
164
+ link = page.link_with(:text => "Form Test")
165
+
166
+ assert_equal "/form_test.html", link.uri.to_s
167
+ assert_equal "http://localhost/form_test.html", link.resolved_uri.to_s
168
+ end unless RUBY_ENGINE == 'jruby' # NekoHTML does not parse body of NOFRAMES
113
169
  end
114
170
 
@@ -8,6 +8,42 @@ class TestMechanizePage < Mechanize::TestCase
8
8
  @uri = URI 'http://example/'
9
9
  end
10
10
 
11
+ def test_selector_methods
12
+ page = html_page <<-BODY
13
+ <html>
14
+ <meta>
15
+ <head><title></title>
16
+ <body>
17
+ <span class="name" id="out">Eamonn</span>
18
+ <span>/</span>
19
+ <span class="name" id="bloody">Esther</span>
20
+ <span>/</span>
21
+ <span class="name" id="rageous">Fletcher</span>
22
+ </body>
23
+ </html>
24
+ BODY
25
+
26
+ # at(css_selector), % css_selector
27
+ assert_equal('Eamonn', page.at('#out').text)
28
+ assert_equal('Eamonn', (page % '#out').text)
29
+
30
+ # at(xpath_selector), % xpath_selector
31
+ assert_equal('Esther', page.at('//span[@id="bloody"]').text)
32
+ assert_equal('Esther', (page % '//span[@id="bloody"]').text)
33
+
34
+ # at_css()
35
+ assert_equal('Eamonn', page.at_css('#out').text)
36
+
37
+ # css()
38
+ assert_equal('Fletcher', page.css('.name')[2].text)
39
+
40
+ # at_xpath()
41
+ assert_equal('Esther', page.at_xpath('//span[@id="bloody"]').text)
42
+
43
+ # xpath()
44
+ assert_equal('Fletcher', page.xpath('//*[@class="name"]')[2].text)
45
+ end
46
+
11
47
  def test_initialize_good_content_type
12
48
  page = Mechanize::Page.new
13
49
  assert_equal('text/html', page.content_type)
@@ -72,6 +108,8 @@ class TestMechanizePage < Mechanize::TestCase
72
108
  assert_equal "frame3", page.frames[2].name
73
109
  assert_equal "/file_upload.html", page.frames[2].src
74
110
  assert_equal "File Upload Form", page.frames[2].content.title
111
+
112
+ assert_equal %w[/google.html /file_upload.html], page.frames_with(search: '*[name=frame1], *[name=frame3]').map(&:src)
75
113
  end
76
114
 
77
115
  def test_iframes
@@ -87,7 +125,7 @@ class TestMechanizePage < Mechanize::TestCase
87
125
  assert_equal "frame4", page.iframes.first.name
88
126
  assert_equal "/file_upload.html", page.iframes.first.src
89
127
  assert_equal "File Upload Form", page.iframes.first.content.title
90
- end
128
+ end unless RUBY_ENGINE == 'jruby' # NekoHTML does not parse IFRAME
91
129
 
92
130
  def test_image_with
93
131
  page = html_page <<-BODY
@@ -174,6 +212,7 @@ class TestMechanizePage < Mechanize::TestCase
174
212
  <meta>
175
213
  <head><title></title>
176
214
  <body>
215
+ <img src="1.jpg" class="unpretty">
177
216
  <img src="a.jpg" class="pretty">
178
217
  <img src="b.jpg">
179
218
  <img src="c.png" class="pretty">
@@ -181,14 +220,24 @@ class TestMechanizePage < Mechanize::TestCase
181
220
  </html>
182
221
  BODY
183
222
 
184
- images = page.images_with(:search => "//img[@class='pretty']")
223
+ {
224
+ :search => "//img[@class='pretty']",
225
+ :xpath => "//img[@class='pretty']",
226
+ :css => "img.pretty",
227
+ :class => "pretty",
228
+ :dom_class => "pretty",
229
+ }.each { |key, expr|
230
+ images = page.images_with(key => expr)
185
231
 
186
- assert_equal 2, images.size
187
- assert_equal "pretty", images[0].dom_class
188
- assert_equal "a.jpg", images[0].src
232
+ message = "selecting with #{key.inspect}"
189
233
 
190
- assert_equal "pretty", images[1].dom_class
191
- assert_equal "c.png", images[1].src
234
+ assert_equal 2, images.size
235
+ assert_equal "pretty", images[0].dom_class, message
236
+ assert_equal "a.jpg", images[0].src, message
237
+
238
+ assert_equal "pretty", images[1].dom_class, message
239
+ assert_equal "c.png", images[1].src, message
240
+ }
192
241
  end
193
242
 
194
243
  def test_search_bad_selectors
@@ -201,5 +250,31 @@ class TestMechanizePage < Mechanize::TestCase
201
250
  assert_empty page.links_with(:search => '//img')
202
251
  end
203
252
 
253
+ def test_multiple_titles
254
+ page = html_page <<-BODY
255
+ <!doctype html>
256
+ <html>
257
+ <head>
258
+ <title>HTML&gt;TITLE</title>
259
+ </head>
260
+ <body>
261
+ <svg>
262
+ <title>SVGTITLE</title>
263
+ <metadata id="metadata5">
264
+ <rdf:RDF>
265
+ <cc:Work>
266
+ <dc:title>RDFDCTITLE</dc:title>
267
+ </cc:Work>
268
+ </rdf:RDF>
269
+ </metadata>
270
+ <g></g>
271
+ </svg>
272
+ </body>
273
+ </html>
274
+ BODY
275
+
276
+ assert_equal page.title, "HTML>TITLE"
277
+ end
278
+
204
279
  end
205
280
 
@@ -5,7 +5,7 @@ require 'mechanize/test_case'
5
5
 
6
6
  class TestMechanizePageEncoding < Mechanize::TestCase
7
7
 
8
- MECH_ASCII_ENCODING = Mechanize::Util::NEW_RUBY_ENCODING ? 'US-ASCII' : 'ISO-8859-1'
8
+ MECH_ASCII_ENCODING = 'US-ASCII'
9
9
 
10
10
  def setup
11
11
  super
@@ -16,8 +16,7 @@ class TestMechanizePageEncoding < Mechanize::TestCase
16
16
  end
17
17
 
18
18
  def util_page body = @body, headers = @response_headers
19
- body.force_encoding Encoding::BINARY if body.respond_to? :force_encoding
20
- Mechanize::Page.new @uri, headers, body, 200, @mech
19
+ Mechanize::Page.new @uri, headers, body && body.force_encoding(Encoding::BINARY), 200, @mech
21
20
  end
22
21
 
23
22
  def test_page_charset