mechanize 2.0.1 → 2.1.pre.1

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 (148) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG.rdoc +82 -0
  3. data/EXAMPLES.rdoc +1 -1
  4. data/FAQ.rdoc +9 -9
  5. data/Manifest.txt +35 -48
  6. data/README.rdoc +2 -1
  7. data/Rakefile +16 -3
  8. data/lib/mechanize.rb +809 -392
  9. data/lib/mechanize/content_type_error.rb +10 -11
  10. data/lib/mechanize/cookie.rb +193 -60
  11. data/lib/mechanize/cookie_jar.rb +39 -86
  12. data/lib/mechanize/download.rb +59 -0
  13. data/lib/mechanize/element_matcher.rb +1 -0
  14. data/lib/mechanize/file.rb +61 -76
  15. data/lib/mechanize/file_saver.rb +37 -35
  16. data/lib/mechanize/form.rb +475 -410
  17. data/lib/mechanize/form/button.rb +4 -7
  18. data/lib/mechanize/form/check_box.rb +10 -9
  19. data/lib/mechanize/form/field.rb +52 -42
  20. data/lib/mechanize/form/file_upload.rb +17 -19
  21. data/lib/mechanize/form/hidden.rb +3 -0
  22. data/lib/mechanize/form/image_button.rb +15 -16
  23. data/lib/mechanize/form/keygen.rb +34 -0
  24. data/lib/mechanize/form/multi_select_list.rb +20 -9
  25. data/lib/mechanize/form/option.rb +48 -47
  26. data/lib/mechanize/form/radio_button.rb +52 -45
  27. data/lib/mechanize/form/reset.rb +3 -0
  28. data/lib/mechanize/form/select_list.rb +10 -6
  29. data/lib/mechanize/form/submit.rb +3 -0
  30. data/lib/mechanize/form/text.rb +3 -0
  31. data/lib/mechanize/form/textarea.rb +3 -0
  32. data/lib/mechanize/headers.rb +17 -19
  33. data/lib/mechanize/history.rb +60 -61
  34. data/lib/mechanize/http.rb +5 -0
  35. data/lib/mechanize/http/agent.rb +485 -218
  36. data/lib/mechanize/http/auth_challenge.rb +59 -0
  37. data/lib/mechanize/http/auth_realm.rb +31 -0
  38. data/lib/mechanize/http/content_disposition_parser.rb +188 -0
  39. data/lib/mechanize/http/www_authenticate_parser.rb +155 -0
  40. data/lib/mechanize/monkey_patch.rb +14 -35
  41. data/lib/mechanize/page.rb +34 -2
  42. data/lib/mechanize/page/base.rb +6 -7
  43. data/lib/mechanize/page/frame.rb +5 -5
  44. data/lib/mechanize/page/image.rb +23 -23
  45. data/lib/mechanize/page/label.rb +16 -16
  46. data/lib/mechanize/page/link.rb +16 -0
  47. data/lib/mechanize/page/meta_refresh.rb +19 -7
  48. data/lib/mechanize/parser.rb +173 -0
  49. data/lib/mechanize/pluggable_parsers.rb +126 -83
  50. data/lib/mechanize/redirect_limit_reached_error.rb +16 -13
  51. data/lib/mechanize/redirect_not_get_or_head_error.rb +18 -16
  52. data/lib/mechanize/response_code_error.rb +16 -17
  53. data/lib/mechanize/robots_disallowed_error.rb +22 -23
  54. data/lib/mechanize/test_case.rb +659 -0
  55. data/lib/mechanize/unauthorized_error.rb +3 -0
  56. data/lib/mechanize/unsupported_scheme_error.rb +4 -6
  57. data/lib/mechanize/util.rb +0 -12
  58. data/test/htdocs/form_order_test.html +11 -0
  59. data/test/htdocs/form_test.html +2 -2
  60. data/test/htdocs/tc_links.html +1 -0
  61. data/test/test_mechanize.rb +367 -59
  62. data/test/test_mechanize_cookie.rb +69 -4
  63. data/test/test_mechanize_cookie_jar.rb +200 -124
  64. data/test/test_mechanize_download.rb +43 -0
  65. data/test/test_mechanize_file.rb +53 -45
  66. data/test/{test_mechanize_file_response.rb → test_mechanize_file_connection.rb} +2 -2
  67. data/test/test_mechanize_file_request.rb +2 -2
  68. data/test/test_mechanize_file_saver.rb +21 -0
  69. data/test/test_mechanize_form.rb +345 -46
  70. data/test/test_mechanize_form_check_box.rb +5 -4
  71. data/test/test_mechanize_form_encoding.rb +10 -16
  72. data/test/test_mechanize_form_field.rb +45 -3
  73. data/test/test_mechanize_form_file_upload.rb +20 -0
  74. data/test/test_mechanize_form_image_button.rb +2 -2
  75. data/test/test_mechanize_form_keygen.rb +32 -0
  76. data/test/test_mechanize_form_multi_select_list.rb +84 -0
  77. data/test/test_mechanize_form_option.rb +55 -0
  78. data/test/test_mechanize_form_radio_button.rb +78 -0
  79. data/test/test_mechanize_form_select_list.rb +76 -0
  80. data/test/test_mechanize_form_textarea.rb +8 -7
  81. data/test/{test_headers.rb → test_mechanize_headers.rb} +4 -2
  82. data/test/test_mechanize_history.rb +103 -0
  83. data/test/test_mechanize_http_agent.rb +525 -17
  84. data/test/test_mechanize_http_auth_challenge.rb +39 -0
  85. data/test/test_mechanize_http_auth_realm.rb +49 -0
  86. data/test/test_mechanize_http_content_disposition_parser.rb +118 -0
  87. data/test/test_mechanize_http_www_authenticate_parser.rb +146 -0
  88. data/test/test_mechanize_link.rb +10 -14
  89. data/test/test_mechanize_page.rb +118 -0
  90. data/test/test_mechanize_page_encoding.rb +48 -13
  91. data/test/test_mechanize_page_frame.rb +16 -0
  92. data/test/test_mechanize_page_link.rb +27 -19
  93. data/test/test_mechanize_page_meta_refresh.rb +26 -14
  94. data/test/test_mechanize_parser.rb +289 -0
  95. data/test/test_mechanize_pluggable_parser.rb +52 -0
  96. data/test/test_mechanize_redirect_limit_reached_error.rb +24 -0
  97. data/test/test_mechanize_redirect_not_get_or_head_error.rb +3 -7
  98. data/test/test_mechanize_subclass.rb +2 -2
  99. data/test/test_mechanize_util.rb +24 -13
  100. data/test/test_multi_select.rb +23 -22
  101. metadata +145 -114
  102. metadata.gz.sig +0 -0
  103. data/lib/mechanize/inspect.rb +0 -88
  104. data/test/helper.rb +0 -175
  105. data/test/htdocs/form_select_all.html +0 -16
  106. data/test/htdocs/form_select_none.html +0 -17
  107. data/test/htdocs/form_select_noopts.html +0 -10
  108. data/test/htdocs/iframe_test.html +0 -16
  109. data/test/htdocs/nofollow.html +0 -9
  110. data/test/htdocs/norobots.html +0 -8
  111. data/test/htdocs/rel_nofollow.html +0 -8
  112. data/test/htdocs/tc_base_images.html +0 -10
  113. data/test/htdocs/tc_images.html +0 -8
  114. data/test/htdocs/tc_no_attributes.html +0 -16
  115. data/test/htdocs/tc_radiobuttons.html +0 -17
  116. data/test/htdocs/test_bad_encoding.html +0 -52
  117. data/test/servlets.rb +0 -402
  118. data/test/ssl_server.rb +0 -48
  119. data/test/test_cookies.rb +0 -129
  120. data/test/test_form_action.rb +0 -52
  121. data/test/test_form_as_hash.rb +0 -59
  122. data/test/test_form_button.rb +0 -46
  123. data/test/test_frames.rb +0 -34
  124. data/test/test_history.rb +0 -118
  125. data/test/test_history_added.rb +0 -16
  126. data/test/test_html_unscape_forms.rb +0 -46
  127. data/test/test_if_modified_since.rb +0 -20
  128. data/test/test_images.rb +0 -19
  129. data/test/test_no_attributes.rb +0 -13
  130. data/test/test_option.rb +0 -18
  131. data/test/test_pluggable_parser.rb +0 -136
  132. data/test/test_post_form.rb +0 -37
  133. data/test/test_pretty_print.rb +0 -22
  134. data/test/test_radiobutton.rb +0 -75
  135. data/test/test_redirect_limit_reached.rb +0 -39
  136. data/test/test_referer.rb +0 -81
  137. data/test/test_relative_links.rb +0 -40
  138. data/test/test_request.rb +0 -13
  139. data/test/test_response_code.rb +0 -53
  140. data/test/test_robots.rb +0 -72
  141. data/test/test_save_file.rb +0 -48
  142. data/test/test_scheme.rb +0 -48
  143. data/test/test_select.rb +0 -119
  144. data/test/test_select_all.rb +0 -15
  145. data/test/test_select_none.rb +0 -15
  146. data/test/test_select_noopts.rb +0 -18
  147. data/test/test_set_fields.rb +0 -44
  148. data/test/test_ssl_server.rb +0 -20
@@ -0,0 +1,39 @@
1
+ require 'mechanize/test_case'
2
+
3
+ class TestMechanizeHttpAuthChallenge < Mechanize::TestCase
4
+
5
+ def setup
6
+ super
7
+
8
+ @uri = URI 'http://example/'
9
+ @AR = Mechanize::HTTP::AuthRealm
10
+ @AC = Mechanize::HTTP::AuthChallenge
11
+ @challenge = @AC.new 'Digest', 'realm' => 'r'
12
+ end
13
+
14
+ def test_realm_basic
15
+ @challenge.scheme = 'Basic'
16
+
17
+ expected = @AR.new 'Basic', @uri, 'r'
18
+
19
+ assert_equal expected, @challenge.realm(@uri + '/foo')
20
+ end
21
+
22
+ def test_realm_digest
23
+ expected = @AR.new 'Digest', @uri, 'r'
24
+
25
+ assert_equal expected, @challenge.realm(@uri + '/foo')
26
+ end
27
+
28
+ def test_realm_unknown
29
+ @challenge.scheme = 'Unknown'
30
+
31
+ e = assert_raises Mechanize::Error do
32
+ @challenge.realm(@uri + '/foo')
33
+ end
34
+
35
+ assert_equal 'unknown HTTP authentication scheme Unknown', e.message
36
+ end
37
+
38
+ end
39
+
@@ -0,0 +1,49 @@
1
+ require 'mechanize/test_case'
2
+
3
+ class TestMechanizeHttpAuthRealm < Mechanize::TestCase
4
+
5
+ def setup
6
+ super
7
+
8
+ @uri = URI 'http://example/'
9
+ @AR = Mechanize::HTTP::AuthRealm
10
+ @realm = @AR.new 'Digest', @uri, 'r'
11
+ end
12
+
13
+ def test_initialize
14
+ assert_equal 'r', @realm.realm
15
+
16
+ realm = @AR.new 'Digest', @uri, 'R'
17
+ assert_equal 'r', realm.realm
18
+
19
+ realm = @AR.new 'Digest', @uri, nil
20
+ assert_nil realm.realm
21
+ end
22
+
23
+ def test_equals2
24
+ other = @realm.dup
25
+ assert_equal @realm, other
26
+
27
+ other = @AR.new 'Basic', @uri, 'r'
28
+ refute_equal @realm, other
29
+
30
+ other = @AR.new 'Digest', URI('http://other.example/'), 'r'
31
+ refute_equal @realm, other
32
+
33
+ other = @AR.new 'Digest', @uri, 's'
34
+ refute_equal @realm, other
35
+ end
36
+
37
+ def test_hash
38
+ h = {}
39
+ h[@realm] = 1
40
+
41
+ other = @realm.dup
42
+ assert_equal 1, h[other]
43
+
44
+ other = @AR.new 'Basic', @uri, 'r'
45
+ assert_nil h[other]
46
+ end
47
+
48
+ end
49
+
@@ -0,0 +1,118 @@
1
+ require 'mechanize/test_case'
2
+
3
+ class TestMechanizeHttpContentDispositionParser < Mechanize::TestCase
4
+
5
+ def setup
6
+ super
7
+
8
+ @parser = Mechanize::HTTP::ContentDispositionParser.new
9
+ end
10
+
11
+ def test_parse
12
+ now = Time.at Time.now.to_i
13
+
14
+ content_disposition = @parser.parse \
15
+ 'attachment;' \
16
+ 'filename=value;' \
17
+ "creation-date=\"#{now.rfc822}\";" \
18
+ "modification-date=\"#{(now + 1).rfc822}\";" \
19
+ "read-date=\"#{(now + 2).rfc822}\";" \
20
+ 'size=5;' \
21
+ 'arbitrary=value'
22
+
23
+ assert_equal 'attachment', content_disposition.type
24
+ assert_equal 'value', content_disposition.filename
25
+ assert_equal now, content_disposition.creation_date
26
+ assert_equal((now + 1), content_disposition.modification_date)
27
+ assert_equal((now + 2), content_disposition.read_date)
28
+ assert_equal 5, content_disposition.size
29
+ expected = { 'arbitrary' => 'value' }
30
+ assert_equal expected, content_disposition.parameters
31
+ end
32
+
33
+ def test_parse_header
34
+ content_disposition = @parser.parse \
35
+ 'content-disposition: attachment;filename=value', true
36
+
37
+ assert_equal 'attachment', content_disposition.type
38
+ assert_equal 'value', content_disposition.filename
39
+ end
40
+
41
+ def test_parse_no_type
42
+ content_disposition = @parser.parse 'filename=value'
43
+
44
+ assert_nil content_disposition.type
45
+ assert_equal 'value', content_disposition.filename
46
+ end
47
+
48
+ def test_parse_semicolons
49
+ content_disposition = @parser.parse 'attachment;;filename=value'
50
+
51
+ assert_equal 'attachment', content_disposition.type
52
+ assert_equal 'value', content_disposition.filename
53
+ end
54
+
55
+ def test_rfc_2045_quoted_string
56
+ @parser.scanner = StringScanner.new '"text"'
57
+
58
+ string = @parser.rfc_2045_quoted_string
59
+
60
+ assert_equal 'text', string
61
+ end
62
+
63
+ def test_rfc_2045_quoted_string_bad
64
+ @parser.scanner = StringScanner.new '"text'
65
+
66
+ assert_nil @parser.rfc_2045_quoted_string
67
+ end
68
+
69
+ def test_rfc_2045_quoted_string_crlf
70
+ @parser.scanner = StringScanner.new "\"multiline\\\r\n\ttext\""
71
+
72
+ string = @parser.rfc_2045_quoted_string
73
+
74
+ assert_equal "multiline\r\n\ttext", string
75
+ end
76
+
77
+ def test_rfc_2045_quoted_string_escape
78
+ @parser.scanner = StringScanner.new "\"escape\\ text\""
79
+
80
+ string = @parser.rfc_2045_quoted_string
81
+
82
+ assert_equal 'escape text', string
83
+ end
84
+
85
+ def test_rfc_2045_quoted_string_escape_bad
86
+ @parser.scanner = StringScanner.new '"escape\\'
87
+
88
+ string = @parser.rfc_2045_quoted_string
89
+
90
+ assert_nil string
91
+ end
92
+
93
+ def test_rfc_2045_quoted_string_folded
94
+ @parser.scanner = StringScanner.new "\"multiline\r\n\ttext\""
95
+
96
+ string = @parser.rfc_2045_quoted_string
97
+
98
+ assert_equal 'multiline text', string
99
+ end
100
+
101
+ def test_rfc_2045_quoted_string_quote
102
+ @parser.scanner = StringScanner.new '"escaped \\" here"'
103
+
104
+ string = @parser.rfc_2045_quoted_string
105
+
106
+ assert_equal 'escaped " here', string
107
+ end
108
+
109
+ def test_rfc_2045_quoted_string_quote_end
110
+ @parser.scanner = StringScanner.new '"end \\""'
111
+
112
+ string = @parser.rfc_2045_quoted_string
113
+
114
+ assert_equal 'end "', string
115
+ end
116
+
117
+ end
118
+
@@ -0,0 +1,146 @@
1
+ require 'mechanize/test_case'
2
+
3
+ class TestMechanizeHttpWwwAuthenticateParser < Mechanize::TestCase
4
+
5
+ def setup
6
+ super
7
+
8
+ @parser = Mechanize::HTTP::WWWAuthenticateParser.new
9
+ end
10
+
11
+ def test_auth_param
12
+ @parser.scanner = StringScanner.new 'realm=here'
13
+
14
+ param = @parser.auth_param
15
+
16
+ assert_equal %w[realm here], param
17
+ end
18
+
19
+ def test_auth_param_bad_no_value
20
+ @parser.scanner = StringScanner.new 'realm='
21
+
22
+ assert_nil @parser.auth_param
23
+ end
24
+
25
+ def test_auth_param_bad_token
26
+ @parser.scanner = StringScanner.new 'realm'
27
+
28
+ assert_nil @parser.auth_param
29
+ end
30
+
31
+ def test_auth_param_bad_value
32
+ @parser.scanner = StringScanner.new 'realm="this '
33
+
34
+ assert_nil @parser.auth_param
35
+ end
36
+
37
+ def test_auth_param_quoted
38
+ @parser.scanner = StringScanner.new 'realm="this site"'
39
+
40
+ param = @parser.auth_param
41
+
42
+ assert_equal ['realm', 'this site'], param
43
+ end
44
+
45
+ def test_parse
46
+ expected = [
47
+ challenge('Basic', { 'realm' => 'foo' }),
48
+ ]
49
+
50
+ assert_equal expected, @parser.parse('Basic realm=foo')
51
+ end
52
+
53
+ def test_parse_multiple
54
+ expected = [
55
+ challenge('Basic', { 'realm' => 'foo' }),
56
+ challenge('Digest', { 'realm' => 'foo' }),
57
+ ]
58
+
59
+ assert_equal expected, @parser.parse('Basic realm=foo, Digest realm=foo')
60
+ end
61
+
62
+ def test_parse_multiple_blank
63
+ expected = [
64
+ challenge('Basic', { 'realm' => 'foo' }),
65
+ challenge('Digest', { 'realm' => 'foo' }),
66
+ ]
67
+
68
+ assert_equal expected, @parser.parse('Basic realm=foo,, Digest realm=foo')
69
+ end
70
+
71
+ def test_parse_ntlm_init
72
+ expected = [
73
+ challenge('NTLM', nil),
74
+ ]
75
+
76
+ assert_equal expected, @parser.parse('NTLM')
77
+ end
78
+
79
+ def test_parse_ntlm_type_2_3
80
+ expected = [
81
+ challenge('NTLM', 'foo='),
82
+ ]
83
+
84
+ assert_equal expected, @parser.parse('NTLM foo=')
85
+ end
86
+
87
+ def test_quoted_string
88
+ @parser.scanner = StringScanner.new '"text"'
89
+
90
+ string = @parser.quoted_string
91
+
92
+ assert_equal 'text', string
93
+ end
94
+
95
+ def test_quoted_string_bad
96
+ @parser.scanner = StringScanner.new '"text'
97
+
98
+ assert_nil @parser.quoted_string
99
+ end
100
+
101
+ def test_quoted_string_quote
102
+ @parser.scanner = StringScanner.new '"escaped \\" here"'
103
+
104
+ string = @parser.quoted_string
105
+
106
+ assert_equal 'escaped \\" here', string
107
+ end
108
+
109
+ def test_quoted_string_quote_end
110
+ @parser.scanner = StringScanner.new '"end \""'
111
+
112
+ string = @parser.quoted_string
113
+
114
+ assert_equal 'end \"', string
115
+ end
116
+
117
+ def test_token
118
+ @parser.scanner = StringScanner.new 'text'
119
+
120
+ string = @parser.token
121
+
122
+ assert_equal 'text', string
123
+ end
124
+
125
+ def test_token_space
126
+ @parser.scanner = StringScanner.new 't ext'
127
+
128
+ string = @parser.token
129
+
130
+ assert_equal 't', string
131
+ end
132
+
133
+ def test_token_special
134
+ @parser.scanner = StringScanner.new "t\text"
135
+
136
+ string = @parser.token
137
+
138
+ assert_equal 't', string
139
+ end
140
+
141
+ def challenge scheme, params
142
+ Mechanize::HTTP::AuthChallenge.new scheme, params
143
+ end
144
+
145
+ end
146
+
@@ -1,35 +1,31 @@
1
- require "helper"
1
+ require 'mechanize/test_case'
2
2
 
3
- class TestMechanizeLink < MiniTest::Unit::TestCase
4
-
5
- def setup
6
- @agent = Mechanize.new
7
- end
3
+ class TestMechanizeLink < Mechanize::TestCase
8
4
 
9
5
  def test_click
10
- page = @agent.get("http://localhost/frame_test.html")
6
+ page = @mech.get("http://localhost/frame_test.html")
11
7
  link = page.link_with(:text => "Form Test")
12
8
 
13
9
  assert_equal('Form Test', link.text)
14
10
  page = link.click
15
11
  assert_equal("http://localhost/form_test.html",
16
- @agent.history.last.uri.to_s)
12
+ @mech.history.last.uri.to_s)
17
13
  end
18
14
 
19
15
  def test_click_base
20
- page = @agent.get("http://google.com/tc_base_link.html")
16
+ page = @mech.get("http://google.com/tc_base_link.html")
21
17
  page = page.links.first.click
22
- assert @agent.visited?("http://localhost/index.html")
18
+ assert @mech.visited?("http://localhost/index.html")
23
19
  end
24
20
 
25
21
  def test_click_unsupported_scheme
26
- page = @agent.get("http://google.com/tc_links.html")
22
+ page = @mech.get("http://google.com/tc_links.html")
27
23
  link = page.link_with(:text => 'javascript link')
28
24
  assert_raises Mechanize::UnsupportedSchemeError do
29
25
  link.click
30
26
  end
31
27
 
32
- @agent.scheme_handlers['javascript'] = lambda { |my_link, my_page|
28
+ @mech.scheme_handlers['javascript'] = lambda { |my_link, my_page|
33
29
  URI.parse('http://localhost/tc_links.html')
34
30
  }
35
31
 
@@ -39,7 +35,7 @@ class TestMechanizeLink < MiniTest::Unit::TestCase
39
35
  end
40
36
 
41
37
  def test_text_alt_text
42
- page = @agent.get("http://localhost/alt_text.html")
38
+ page = @mech.get("http://localhost/alt_text.html")
43
39
  assert_equal(5, page.links.length)
44
40
  assert_equal(1, page.meta_refresh.length)
45
41
 
@@ -63,7 +59,7 @@ class TestMechanizeLink < MiniTest::Unit::TestCase
63
59
  end
64
60
 
65
61
  def test_uri_no_path
66
- page = @agent.get("http://localhost/relative/tc_relative_links.html")
62
+ page = @mech.get("http://localhost/relative/tc_relative_links.html")
67
63
  page = page.link_with(:text => 'just the query string').click
68
64
  assert_equal('http://localhost/relative/tc_relative_links.html?a=b',
69
65
  page.uri.to_s)
@@ -0,0 +1,118 @@
1
+ require 'mechanize/test_case'
2
+
3
+ class TestMechanizePage < Mechanize::TestCase
4
+
5
+ def setup
6
+ super
7
+
8
+ @uri = URI 'http://example/'
9
+ end
10
+
11
+ def test_initialize_bad_content_type
12
+ e = assert_raises Mechanize::ContentTypeError do
13
+ Mechanize::Page.new(URI('http://example/'),
14
+ { 'content-type' => 'text/xml' }, 'hello', '200')
15
+ end
16
+
17
+ assert_equal('text/xml', e.content_type)
18
+ end
19
+
20
+ def test_frames
21
+ page = html_page <<-BODY
22
+ <TITLE>A simple frameset document</TITLE>
23
+ <FRAMESET cols="20%, 80%">
24
+ <FRAMESET rows="100, 200">
25
+ <FRAME name="frame1" src="/google.html">
26
+ <FRAME name="frame2" src="/form_test.html">
27
+ </FRAMESET>
28
+ <FRAMESET rows="100, 200">
29
+ <FRAME name="frame3" src="/file_upload.html">
30
+ <IFRAME src="http://google.com/" name="frame4"></IFRAME>
31
+ </FRAMESET>
32
+ </FRAMESET>
33
+ BODY
34
+
35
+ assert_equal 3, page.frames.size
36
+ assert_equal "frame1", page.frames[0].name
37
+ assert_equal "/google.html", page.frames[0].src
38
+ assert_equal "Google", page.frames[0].content.title
39
+
40
+ assert_equal "frame2", page.frames[1].name
41
+ assert_equal "/form_test.html", page.frames[1].src
42
+ assert_equal "Page Title", page.frames[1].content.title
43
+
44
+ assert_equal "frame3", page.frames[2].name
45
+ assert_equal "/file_upload.html", page.frames[2].src
46
+ assert_equal "File Upload Form", page.frames[2].content.title
47
+ end
48
+
49
+ def test_iframes
50
+ page = html_page <<-BODY
51
+ <TITLE>A simple frameset document</TITLE>
52
+ <FRAME name="frame1" src="/google.html">
53
+ <IFRAME src="/file_upload.html" name="frame4">
54
+ </IFRAME>
55
+ BODY
56
+
57
+ assert_equal 1, page.iframes.size
58
+
59
+ assert_equal "frame4", page.iframes.first.name
60
+ assert_equal "/file_upload.html", page.iframes.first.src
61
+ assert_equal "File Upload Form", page.iframes.first.content.title
62
+ end
63
+
64
+ def test_images
65
+ page = html_page <<-BODY
66
+ <img src="a.jpg">
67
+ BODY
68
+
69
+ assert_equal page.images.first.url, "http://example/a.jpg"
70
+ end
71
+
72
+ def test_images_base
73
+ page = html_page <<-BODY
74
+ <head>
75
+ <base href="http://other.example/">
76
+ </head>
77
+ <body>
78
+ <img src="a.jpg">
79
+ </body>
80
+ BODY
81
+
82
+ assert_equal page.images.first.url, "http://other.example/a.jpg"
83
+ end
84
+
85
+ def test_links
86
+ page = html_page <<-BODY
87
+ <a href="foo.html">
88
+ BODY
89
+
90
+ assert_equal page.links.first.href, "foo.html"
91
+ end
92
+
93
+ def test_parser_no_attributes
94
+ page = html_page <<-BODY
95
+ <html>
96
+ <meta>
97
+ <head><title></title>
98
+ <body>
99
+ <a>Hello</a>
100
+ <a><img /></a>
101
+ <form>
102
+ <input />
103
+ <select>
104
+ <option />
105
+ </select>
106
+ <textarea></textarea>
107
+ </form>
108
+ <frame></frame>
109
+ </body>
110
+ </html>
111
+ BODY
112
+
113
+ # HACK weak assertion
114
+ assert_kind_of Nokogiri::HTML::Document, page.root
115
+ end
116
+
117
+ end
118
+