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.
- checksums.yaml +5 -5
- data/.github/workflows/ci-test.yml +45 -0
- data/.gitignore +15 -0
- data/.yardopts +8 -0
- data/{CHANGELOG.rdoc → CHANGELOG.md} +149 -62
- data/EXAMPLES.rdoc +2 -25
- data/Gemfile +3 -0
- data/{LICENSE.rdoc → LICENSE.txt} +4 -0
- data/README.md +79 -0
- data/Rakefile +36 -37
- data/examples/{rubyforge.rb → rubygems.rb} +7 -6
- data/lib/mechanize.rb +75 -33
- data/lib/mechanize/chunked_termination_error.rb +1 -0
- data/lib/mechanize/content_type_error.rb +1 -0
- data/lib/mechanize/cookie.rb +1 -13
- data/lib/mechanize/cookie_jar.rb +4 -12
- data/lib/mechanize/directory_saver.rb +15 -2
- data/lib/mechanize/download.rb +2 -1
- data/lib/mechanize/element_matcher.rb +29 -14
- data/lib/mechanize/element_not_found_error.rb +1 -0
- data/lib/mechanize/file.rb +2 -1
- data/lib/mechanize/file_connection.rb +5 -3
- data/lib/mechanize/file_request.rb +1 -0
- data/lib/mechanize/file_response.rb +5 -4
- data/lib/mechanize/file_saver.rb +1 -0
- data/lib/mechanize/form.rb +119 -46
- data/lib/mechanize/form/button.rb +1 -0
- data/lib/mechanize/form/check_box.rb +1 -0
- data/lib/mechanize/form/field.rb +47 -0
- data/lib/mechanize/form/file_upload.rb +1 -0
- data/lib/mechanize/form/hidden.rb +1 -0
- data/lib/mechanize/form/image_button.rb +1 -0
- data/lib/mechanize/form/keygen.rb +1 -0
- data/lib/mechanize/form/multi_select_list.rb +8 -14
- data/lib/mechanize/form/option.rb +3 -1
- data/lib/mechanize/form/radio_button.rb +1 -0
- data/lib/mechanize/form/reset.rb +1 -0
- data/lib/mechanize/form/select_list.rb +1 -0
- data/lib/mechanize/form/submit.rb +1 -0
- data/lib/mechanize/form/text.rb +1 -0
- data/lib/mechanize/form/textarea.rb +1 -0
- data/lib/mechanize/headers.rb +1 -0
- data/lib/mechanize/history.rb +2 -1
- data/lib/mechanize/http.rb +1 -0
- data/lib/mechanize/http/agent.rb +115 -64
- data/lib/mechanize/http/auth_challenge.rb +1 -0
- data/lib/mechanize/http/auth_realm.rb +2 -1
- data/lib/mechanize/http/auth_store.rb +3 -0
- data/lib/mechanize/http/content_disposition_parser.rb +18 -3
- data/lib/mechanize/http/www_authenticate_parser.rb +5 -5
- data/lib/mechanize/image.rb +1 -0
- data/lib/mechanize/page.rb +166 -55
- data/lib/mechanize/page/base.rb +1 -0
- data/lib/mechanize/page/frame.rb +4 -1
- data/lib/mechanize/page/image.rb +3 -0
- data/lib/mechanize/page/label.rb +1 -0
- data/lib/mechanize/page/link.rb +13 -1
- data/lib/mechanize/page/meta_refresh.rb +1 -0
- data/lib/mechanize/parser.rb +4 -3
- data/lib/mechanize/pluggable_parsers.rb +14 -1
- data/lib/mechanize/prependable.rb +1 -0
- data/lib/mechanize/redirect_limit_reached_error.rb +1 -0
- data/lib/mechanize/redirect_not_get_or_head_error.rb +1 -0
- data/lib/mechanize/response_code_error.rb +2 -1
- data/lib/mechanize/response_read_error.rb +1 -0
- data/lib/mechanize/robots_disallowed_error.rb +1 -0
- data/lib/mechanize/test_case.rb +39 -29
- data/lib/mechanize/test_case/bad_chunking_servlet.rb +1 -0
- data/lib/mechanize/test_case/basic_auth_servlet.rb +1 -0
- data/lib/mechanize/test_case/content_type_servlet.rb +1 -0
- data/lib/mechanize/test_case/digest_auth_servlet.rb +1 -0
- data/lib/mechanize/test_case/file_upload_servlet.rb +1 -0
- data/lib/mechanize/test_case/form_servlet.rb +1 -0
- data/lib/mechanize/test_case/gzip_servlet.rb +4 -3
- data/lib/mechanize/test_case/header_servlet.rb +1 -0
- data/lib/mechanize/test_case/http_refresh_servlet.rb +2 -2
- data/lib/mechanize/test_case/infinite_redirect_servlet.rb +1 -0
- data/lib/mechanize/test_case/infinite_refresh_servlet.rb +2 -2
- data/lib/mechanize/test_case/many_cookies_as_string_servlet.rb +1 -0
- data/lib/mechanize/test_case/many_cookies_servlet.rb +1 -0
- data/lib/mechanize/test_case/modified_since_servlet.rb +1 -0
- data/lib/mechanize/test_case/ntlm_servlet.rb +1 -0
- data/lib/mechanize/test_case/one_cookie_no_spaces_servlet.rb +1 -0
- data/lib/mechanize/test_case/one_cookie_servlet.rb +1 -0
- data/lib/mechanize/test_case/quoted_value_cookie_servlet.rb +1 -0
- data/lib/mechanize/test_case/redirect_servlet.rb +1 -0
- data/lib/mechanize/test_case/referer_servlet.rb +1 -0
- data/lib/mechanize/test_case/refresh_with_empty_url.rb +1 -0
- data/lib/mechanize/test_case/refresh_without_url.rb +1 -0
- data/lib/mechanize/test_case/response_code_servlet.rb +1 -0
- data/lib/mechanize/test_case/robots_txt_servlet.rb +15 -0
- data/lib/mechanize/test_case/send_cookies_servlet.rb +1 -0
- data/lib/mechanize/test_case/server.rb +1 -0
- data/lib/mechanize/test_case/servlets.rb +4 -0
- data/lib/mechanize/test_case/verb_servlet.rb +5 -6
- data/lib/mechanize/unauthorized_error.rb +2 -1
- data/lib/mechanize/unsupported_scheme_error.rb +5 -2
- data/lib/mechanize/util.rb +90 -43
- data/lib/mechanize/version.rb +4 -0
- data/lib/mechanize/xml_file.rb +1 -0
- data/mechanize.gemspec +69 -0
- data/test/htdocs/dir with spaces/foo.html +1 -0
- data/test/htdocs/find_link.html +1 -4
- data/test/htdocs/tc_links.html +1 -1
- data/test/test_mechanize.rb +111 -55
- data/test/test_mechanize_cookie.rb +75 -60
- data/test/test_mechanize_cookie_jar.rb +112 -59
- data/test/test_mechanize_download.rb +13 -1
- data/test/test_mechanize_file.rb +10 -0
- data/test/test_mechanize_file_connection.rb +21 -3
- data/test/test_mechanize_file_response.rb +26 -2
- data/test/test_mechanize_form.rb +46 -11
- data/test/test_mechanize_form_check_box.rb +10 -0
- data/test/test_mechanize_form_encoding.rb +3 -8
- data/test/test_mechanize_form_keygen.rb +1 -0
- data/test/test_mechanize_form_multi_select_list.rb +5 -1
- data/test/test_mechanize_http_agent.rb +175 -18
- data/test/test_mechanize_http_auth_challenge.rb +14 -0
- data/test/test_mechanize_http_auth_realm.rb +7 -1
- data/test/test_mechanize_http_auth_store.rb +37 -0
- data/test/test_mechanize_http_content_disposition_parser.rb +35 -1
- data/test/test_mechanize_http_www_authenticate_parser.rb +24 -0
- data/test/test_mechanize_link.rb +60 -4
- data/test/test_mechanize_page.rb +82 -7
- data/test/test_mechanize_page_encoding.rb +2 -3
- data/test/test_mechanize_page_image.rb +1 -1
- data/test/test_mechanize_page_link.rb +20 -5
- data/test/test_mechanize_page_meta_refresh.rb +1 -1
- data/test/test_mechanize_parser.rb +12 -2
- data/test/test_mechanize_util.rb +46 -11
- metadata +198 -99
- data/.gemtest +0 -0
- data/.travis.yml +0 -26
- data/Manifest.txt +0 -205
- data/README.rdoc +0 -83
- data/lib/mechanize/monkey_patch.rb +0 -17
- 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
|
-
|
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
|
|
data/test/test_mechanize_link.rb
CHANGED
@@ -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
|
-
|
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
|
|
data/test/test_mechanize_page.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
191
|
-
|
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>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 =
|
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
|
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
|