diamond-mechanize 2.1 → 2.2
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.
- metadata +222 -167
- data/Rakefile +0 -49
- data/lib/mechanize/content_type_error.rb +0 -13
- data/lib/mechanize/cookie.rb +0 -232
- data/lib/mechanize/cookie_jar.rb +0 -194
- data/lib/mechanize/download.rb +0 -59
- data/lib/mechanize/element_matcher.rb +0 -36
- data/lib/mechanize/file.rb +0 -65
- data/lib/mechanize/file_connection.rb +0 -17
- data/lib/mechanize/file_request.rb +0 -26
- data/lib/mechanize/file_response.rb +0 -74
- data/lib/mechanize/file_saver.rb +0 -39
- data/lib/mechanize/form/button.rb +0 -6
- data/lib/mechanize/form/check_box.rb +0 -12
- data/lib/mechanize/form/field.rb +0 -54
- data/lib/mechanize/form/file_upload.rb +0 -21
- data/lib/mechanize/form/hidden.rb +0 -3
- data/lib/mechanize/form/image_button.rb +0 -19
- data/lib/mechanize/form/keygen.rb +0 -34
- data/lib/mechanize/form/multi_select_list.rb +0 -94
- data/lib/mechanize/form/option.rb +0 -50
- data/lib/mechanize/form/radio_button.rb +0 -55
- data/lib/mechanize/form/reset.rb +0 -3
- data/lib/mechanize/form/select_list.rb +0 -44
- data/lib/mechanize/form/submit.rb +0 -3
- data/lib/mechanize/form/text.rb +0 -3
- data/lib/mechanize/form/textarea.rb +0 -3
- data/lib/mechanize/form.rb +0 -543
- data/lib/mechanize/headers.rb +0 -23
- data/lib/mechanize/history.rb +0 -82
- data/lib/mechanize/http/agent.rb +0 -1004
- data/lib/mechanize/http/auth_challenge.rb +0 -59
- data/lib/mechanize/http/auth_realm.rb +0 -31
- data/lib/mechanize/http/content_disposition_parser.rb +0 -188
- data/lib/mechanize/http/www_authenticate_parser.rb +0 -155
- data/lib/mechanize/http.rb +0 -8
- data/lib/mechanize/monkey_patch.rb +0 -16
- data/lib/mechanize/page/base.rb +0 -7
- data/lib/mechanize/page/frame.rb +0 -27
- data/lib/mechanize/page/image.rb +0 -30
- data/lib/mechanize/page/label.rb +0 -20
- data/lib/mechanize/page/link.rb +0 -98
- data/lib/mechanize/page/meta_refresh.rb +0 -68
- data/lib/mechanize/page.rb +0 -440
- data/lib/mechanize/parser.rb +0 -173
- data/lib/mechanize/pluggable_parsers.rb +0 -144
- data/lib/mechanize/redirect_limit_reached_error.rb +0 -19
- data/lib/mechanize/redirect_not_get_or_head_error.rb +0 -21
- data/lib/mechanize/response_code_error.rb +0 -21
- data/lib/mechanize/response_read_error.rb +0 -27
- data/lib/mechanize/robots_disallowed_error.rb +0 -28
- data/lib/mechanize/test_case.rb +0 -663
- data/lib/mechanize/unauthorized_error.rb +0 -3
- data/lib/mechanize/unsupported_scheme_error.rb +0 -6
- data/lib/mechanize/util.rb +0 -101
- data/lib/mechanize.rb +0 -1079
- data/test/data/htpasswd +0 -1
- data/test/data/server.crt +0 -16
- data/test/data/server.csr +0 -12
- data/test/data/server.key +0 -15
- data/test/data/server.pem +0 -15
- data/test/htdocs/alt_text.html +0 -10
- data/test/htdocs/bad_form_test.html +0 -9
- data/test/htdocs/button.jpg +0 -0
- data/test/htdocs/canonical_uri.html +0 -9
- data/test/htdocs/dir with spaces/foo.html +0 -1
- data/test/htdocs/empty_form.html +0 -6
- data/test/htdocs/file_upload.html +0 -26
- data/test/htdocs/find_link.html +0 -41
- data/test/htdocs/form_multi_select.html +0 -16
- data/test/htdocs/form_multival.html +0 -37
- data/test/htdocs/form_no_action.html +0 -18
- data/test/htdocs/form_no_input_name.html +0 -16
- data/test/htdocs/form_order_test.html +0 -11
- data/test/htdocs/form_select.html +0 -16
- data/test/htdocs/form_set_fields.html +0 -14
- data/test/htdocs/form_test.html +0 -188
- data/test/htdocs/frame_referer_test.html +0 -10
- data/test/htdocs/frame_test.html +0 -30
- data/test/htdocs/google.html +0 -13
- data/test/htdocs/index.html +0 -6
- data/test/htdocs/link with space.html +0 -5
- data/test/htdocs/meta_cookie.html +0 -11
- data/test/htdocs/no_title_test.html +0 -6
- data/test/htdocs/noindex.html +0 -9
- data/test/htdocs/rails_3_encoding_hack_form_test.html +0 -27
- data/test/htdocs/relative/tc_relative_links.html +0 -21
- data/test/htdocs/robots.html +0 -8
- data/test/htdocs/robots.txt +0 -2
- data/test/htdocs/tc_bad_charset.html +0 -9
- data/test/htdocs/tc_bad_links.html +0 -5
- data/test/htdocs/tc_base_link.html +0 -8
- data/test/htdocs/tc_blank_form.html +0 -11
- data/test/htdocs/tc_charset.html +0 -6
- data/test/htdocs/tc_checkboxes.html +0 -19
- data/test/htdocs/tc_encoded_links.html +0 -5
- data/test/htdocs/tc_field_precedence.html +0 -11
- data/test/htdocs/tc_follow_meta.html +0 -8
- data/test/htdocs/tc_form_action.html +0 -48
- data/test/htdocs/tc_links.html +0 -19
- data/test/htdocs/tc_meta_in_body.html +0 -9
- data/test/htdocs/tc_pretty_print.html +0 -17
- data/test/htdocs/tc_referer.html +0 -16
- data/test/htdocs/tc_relative_links.html +0 -19
- data/test/htdocs/tc_textarea.html +0 -23
- data/test/htdocs/test_click.html +0 -11
- data/test/htdocs/unusual______.html +0 -5
- data/test/test_mechanize.rb +0 -1164
- data/test/test_mechanize_cookie.rb +0 -451
- data/test/test_mechanize_cookie_jar.rb +0 -483
- data/test/test_mechanize_download.rb +0 -43
- data/test/test_mechanize_file.rb +0 -61
- data/test/test_mechanize_file_connection.rb +0 -21
- data/test/test_mechanize_file_request.rb +0 -19
- data/test/test_mechanize_file_saver.rb +0 -21
- data/test/test_mechanize_form.rb +0 -875
- data/test/test_mechanize_form_check_box.rb +0 -38
- data/test/test_mechanize_form_encoding.rb +0 -114
- data/test/test_mechanize_form_field.rb +0 -63
- data/test/test_mechanize_form_file_upload.rb +0 -20
- data/test/test_mechanize_form_image_button.rb +0 -12
- data/test/test_mechanize_form_keygen.rb +0 -32
- data/test/test_mechanize_form_multi_select_list.rb +0 -84
- data/test/test_mechanize_form_option.rb +0 -55
- data/test/test_mechanize_form_radio_button.rb +0 -78
- data/test/test_mechanize_form_select_list.rb +0 -76
- data/test/test_mechanize_form_textarea.rb +0 -52
- data/test/test_mechanize_headers.rb +0 -35
- data/test/test_mechanize_history.rb +0 -103
- data/test/test_mechanize_http_agent.rb +0 -1225
- data/test/test_mechanize_http_auth_challenge.rb +0 -39
- data/test/test_mechanize_http_auth_realm.rb +0 -49
- data/test/test_mechanize_http_content_disposition_parser.rb +0 -118
- data/test/test_mechanize_http_www_authenticate_parser.rb +0 -146
- data/test/test_mechanize_link.rb +0 -80
- data/test/test_mechanize_page.rb +0 -118
- data/test/test_mechanize_page_encoding.rb +0 -182
- data/test/test_mechanize_page_frame.rb +0 -16
- data/test/test_mechanize_page_link.rb +0 -390
- data/test/test_mechanize_page_meta_refresh.rb +0 -127
- data/test/test_mechanize_parser.rb +0 -289
- data/test/test_mechanize_pluggable_parser.rb +0 -52
- data/test/test_mechanize_redirect_limit_reached_error.rb +0 -24
- data/test/test_mechanize_redirect_not_get_or_head_error.rb +0 -14
- data/test/test_mechanize_subclass.rb +0 -22
- data/test/test_mechanize_util.rb +0 -103
- data/test/test_multi_select.rb +0 -119
@@ -1,50 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# This class contains an option found within SelectList. A SelectList can
|
3
|
-
# have many Option classes associated with it. An option can be selected by
|
4
|
-
# calling Option#tick, or Option#click.
|
5
|
-
#
|
6
|
-
# To select the first option in a list:
|
7
|
-
#
|
8
|
-
# select_list.first.tick
|
9
|
-
|
10
|
-
class Mechanize::Form::Option
|
11
|
-
attr_reader :value, :selected, :text, :select_list
|
12
|
-
|
13
|
-
alias :to_s :value
|
14
|
-
alias :selected? :selected
|
15
|
-
|
16
|
-
def initialize(node, select_list)
|
17
|
-
@text = node.inner_text
|
18
|
-
@value = Mechanize::Util.html_unescape(node['value'] || node.inner_text)
|
19
|
-
@selected = node.has_attribute? 'selected'
|
20
|
-
@select_list = select_list # The select list this option belongs to
|
21
|
-
end
|
22
|
-
|
23
|
-
# Select this option
|
24
|
-
def select
|
25
|
-
unselect_peers
|
26
|
-
@selected = true
|
27
|
-
end
|
28
|
-
|
29
|
-
# Unselect this option
|
30
|
-
def unselect
|
31
|
-
@selected = false
|
32
|
-
end
|
33
|
-
|
34
|
-
alias :tick :select
|
35
|
-
alias :untick :unselect
|
36
|
-
|
37
|
-
# Toggle the selection value of this option
|
38
|
-
def click
|
39
|
-
unselect_peers
|
40
|
-
@selected = !@selected
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
def unselect_peers
|
45
|
-
return unless Mechanize::Form::SelectList === @select_list
|
46
|
-
|
47
|
-
@select_list.select_none
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
@@ -1,55 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# This class represents a radio button found in a Form. To activate the
|
3
|
-
# RadioButton in the Form, set the checked method to true.
|
4
|
-
|
5
|
-
class Mechanize::Form::RadioButton < Mechanize::Form::Field
|
6
|
-
attr_accessor :checked
|
7
|
-
|
8
|
-
def initialize node, form
|
9
|
-
@checked = !!node['checked']
|
10
|
-
@form = form
|
11
|
-
super(node)
|
12
|
-
end
|
13
|
-
|
14
|
-
def check
|
15
|
-
uncheck_peers
|
16
|
-
@checked = true
|
17
|
-
end
|
18
|
-
|
19
|
-
alias checked? checked
|
20
|
-
|
21
|
-
def uncheck
|
22
|
-
@checked = false
|
23
|
-
end
|
24
|
-
|
25
|
-
def click
|
26
|
-
checked ? uncheck : check
|
27
|
-
end
|
28
|
-
|
29
|
-
def label
|
30
|
-
(id = self['id']) && @form.page.labels_hash[id] || nil
|
31
|
-
end
|
32
|
-
|
33
|
-
def text
|
34
|
-
label.text rescue nil
|
35
|
-
end
|
36
|
-
|
37
|
-
def [](key)
|
38
|
-
@node[key]
|
39
|
-
end
|
40
|
-
|
41
|
-
def pretty_print_instance_variables # :nodoc:
|
42
|
-
[:@checked, :@name, :@value]
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def uncheck_peers
|
48
|
-
@form.radiobuttons_with(:name => name).each do |b|
|
49
|
-
next if b.value == value
|
50
|
-
b.uncheck
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
end
|
55
|
-
|
data/lib/mechanize/form/reset.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
# This class represents a select list or drop down box in a Form. Set the
|
2
|
-
# value for the list by calling SelectList#value=. SelectList contains a list
|
3
|
-
# of Option that were found. After finding the correct option, set the select
|
4
|
-
# lists value to the option value:
|
5
|
-
#
|
6
|
-
# selectlist.value = selectlist.options.first.value
|
7
|
-
#
|
8
|
-
# Options can also be selected by "clicking" or selecting them. See Option
|
9
|
-
class Mechanize::Form::SelectList < Mechanize::Form::MultiSelectList
|
10
|
-
|
11
|
-
def initialize node
|
12
|
-
super
|
13
|
-
if selected_options.length > 1
|
14
|
-
selected_options.reverse[1..selected_options.length].each do |o|
|
15
|
-
o.unselect
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def value
|
21
|
-
value = super
|
22
|
-
if value.length > 0
|
23
|
-
value.last
|
24
|
-
elsif @options.length > 0
|
25
|
-
@options.first.value
|
26
|
-
else
|
27
|
-
nil
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def value=(new)
|
32
|
-
if new != new.to_s and new.respond_to? :first
|
33
|
-
super([new.first])
|
34
|
-
else
|
35
|
-
super([new.to_s])
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def query_value
|
40
|
-
value ? [[name, value]] : nil
|
41
|
-
end
|
42
|
-
|
43
|
-
end
|
44
|
-
|
data/lib/mechanize/form/text.rb
DELETED
data/lib/mechanize/form.rb
DELETED
@@ -1,543 +0,0 @@
|
|
1
|
-
require 'mechanize/element_matcher'
|
2
|
-
|
3
|
-
# This class encapsulates a form parsed out of an HTML page. Each type of
|
4
|
-
# input fields available in a form can be accessed through this object.
|
5
|
-
#
|
6
|
-
# == Examples
|
7
|
-
#
|
8
|
-
# Find a form and print out its fields
|
9
|
-
#
|
10
|
-
# form = page.forms.first # => Mechanize::Form
|
11
|
-
# form.fields.each { |f| puts f.name }
|
12
|
-
#
|
13
|
-
# Set the input field 'name' to "Aaron"
|
14
|
-
#
|
15
|
-
# form['name'] = 'Aaron'
|
16
|
-
# puts form['name']
|
17
|
-
|
18
|
-
class Mechanize::Form
|
19
|
-
|
20
|
-
extend Mechanize::ElementMatcher
|
21
|
-
|
22
|
-
attr_accessor :method, :action, :name
|
23
|
-
|
24
|
-
attr_reader :fields, :buttons, :file_uploads, :radiobuttons, :checkboxes
|
25
|
-
|
26
|
-
# Content-Type for form data (i.e. application/x-www-form-urlencoded)
|
27
|
-
attr_accessor :enctype
|
28
|
-
|
29
|
-
# Character encoding of form data (i.e. UTF-8)
|
30
|
-
attr_accessor :encoding
|
31
|
-
|
32
|
-
# When true, character encoding errors will never be never raised on form
|
33
|
-
# submission. Default is false
|
34
|
-
attr_accessor :ignore_encoding_error
|
35
|
-
|
36
|
-
alias :elements :fields
|
37
|
-
|
38
|
-
attr_reader :form_node
|
39
|
-
attr_reader :page
|
40
|
-
|
41
|
-
def initialize(node, mech=nil, page=nil)
|
42
|
-
@enctype = node['enctype'] || 'application/x-www-form-urlencoded'
|
43
|
-
@form_node = node
|
44
|
-
@action = Mechanize::Util.html_unescape(node['action'])
|
45
|
-
@method = (node['method'] || 'GET').upcase
|
46
|
-
@name = node['name']
|
47
|
-
@clicked_buttons = []
|
48
|
-
@page = page
|
49
|
-
@mech = mech
|
50
|
-
|
51
|
-
@encoding = node['accept-charset'] || (page && page.encoding) || nil
|
52
|
-
@ignore_encoding_error = false
|
53
|
-
parse
|
54
|
-
end
|
55
|
-
|
56
|
-
# Returns whether or not the form contains a field with +field_name+
|
57
|
-
def has_field?(field_name)
|
58
|
-
fields.find { |f| f.name == field_name }
|
59
|
-
end
|
60
|
-
|
61
|
-
alias :has_key? :has_field?
|
62
|
-
|
63
|
-
def has_value?(value)
|
64
|
-
fields.find { |f| f.value == value }
|
65
|
-
end
|
66
|
-
|
67
|
-
def keys; fields.map { |f| f.name }; end
|
68
|
-
|
69
|
-
def values; fields.map { |f| f.value }; end
|
70
|
-
|
71
|
-
def submits ; @submits ||= buttons.select { |f| f.class == Submit }; end
|
72
|
-
def resets ; @resets ||= buttons.select { |f| f.class == Reset }; end
|
73
|
-
def texts ; @texts ||= fields.select { |f| f.class == Text }; end
|
74
|
-
def hiddens ; @hiddens ||= fields.select { |f| f.class == Hidden }; end
|
75
|
-
def textareas; @textareas ||= fields.select { |f| f.class == Textarea }; end
|
76
|
-
def keygens ; @keygens ||= fields.select { |f| f.class == Keygen }; end
|
77
|
-
|
78
|
-
def submit_button?(button_name) submits.find{|f| f.name == button_name}; end
|
79
|
-
def reset_button?(button_name) resets.find{|f| f.name == button_name}; end
|
80
|
-
def text_field?(field_name) texts.find{|f| f.name == field_name}; end
|
81
|
-
def hidden_field?(field_name) hiddens.find{|f| f.name == field_name}; end
|
82
|
-
def textarea_field?(field_name) textareas.find{|f| f.name == field_name}; end
|
83
|
-
|
84
|
-
# This method is a shortcut to get form's DOM id.
|
85
|
-
# Common usage:
|
86
|
-
# page.form_with(:dom_id => "foorm")
|
87
|
-
# Note that you can also use +:id+ to get to this method:
|
88
|
-
# page.form_with(:id => "foorm")
|
89
|
-
def dom_id
|
90
|
-
form_node['id']
|
91
|
-
end
|
92
|
-
|
93
|
-
# This method is a shortcut to get form's DOM class.
|
94
|
-
# Common usage:
|
95
|
-
# page.form_with(:dom_class => "foorm")
|
96
|
-
# Note that you can also use +:class+ to get to this method:
|
97
|
-
# page.form_with(:class => "foorm")
|
98
|
-
def dom_class
|
99
|
-
form_node['class']
|
100
|
-
end
|
101
|
-
|
102
|
-
# Add a field with +field_name+ and +value+
|
103
|
-
def add_field!(field_name, value = nil)
|
104
|
-
fields << Field.new({'name' => field_name}, value)
|
105
|
-
end
|
106
|
-
|
107
|
-
##
|
108
|
-
# This method sets multiple fields on the form. It takes a list of +fields+
|
109
|
-
# which are name, value pairs.
|
110
|
-
#
|
111
|
-
# If there is more than one field found with the same name, this method will
|
112
|
-
# set the first one found. If you want to set the value of a duplicate
|
113
|
-
# field, use a value which is a Hash with the key as the index in to the
|
114
|
-
# form. The index is zero based.
|
115
|
-
#
|
116
|
-
# For example, to set the second field named 'foo', you could do the
|
117
|
-
# following:
|
118
|
-
#
|
119
|
-
# form.set_fields :foo => { 1 => 'bar' }
|
120
|
-
|
121
|
-
def set_fields fields = {}
|
122
|
-
fields.each do |name, v|
|
123
|
-
case v
|
124
|
-
when Hash
|
125
|
-
v.each do |index, value|
|
126
|
-
self.fields_with(:name => name.to_s)[index].value = value
|
127
|
-
end
|
128
|
-
else
|
129
|
-
value = nil
|
130
|
-
index = 0
|
131
|
-
|
132
|
-
[v].flatten.each do |val|
|
133
|
-
index = val.to_i if value
|
134
|
-
value = val unless value
|
135
|
-
end
|
136
|
-
|
137
|
-
self.fields_with(:name => name.to_s)[index].value = value
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
# Fetch the value of the first input field with the name passed in
|
143
|
-
# ==Example
|
144
|
-
# Fetch the value set in the input field 'name'
|
145
|
-
# puts form['name']
|
146
|
-
def [](field_name)
|
147
|
-
f = field(field_name)
|
148
|
-
f && f.value
|
149
|
-
end
|
150
|
-
|
151
|
-
# Set the value of the first input field with the name passed in
|
152
|
-
# ==Example
|
153
|
-
# Set the value in the input field 'name' to "Aaron"
|
154
|
-
# form['name'] = 'Aaron'
|
155
|
-
def []=(field_name, value)
|
156
|
-
f = field(field_name)
|
157
|
-
if f
|
158
|
-
f.value = value
|
159
|
-
else
|
160
|
-
add_field!(field_name, value)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
# Treat form fields like accessors.
|
165
|
-
def method_missing(meth, *args)
|
166
|
-
method = meth.to_s.gsub(/=$/, '')
|
167
|
-
|
168
|
-
if field(method)
|
169
|
-
return field(method).value if args.empty?
|
170
|
-
return field(method).value = args[0]
|
171
|
-
end
|
172
|
-
|
173
|
-
super
|
174
|
-
end
|
175
|
-
|
176
|
-
# Submit this form with the button passed in
|
177
|
-
def submit button=nil, headers = {}
|
178
|
-
@mech.submit(self, button, headers)
|
179
|
-
end
|
180
|
-
|
181
|
-
# Submit form using +button+. Defaults
|
182
|
-
# to the first button.
|
183
|
-
def click_button(button = buttons.first)
|
184
|
-
submit(button)
|
185
|
-
end
|
186
|
-
|
187
|
-
# This method is sub-method of build_query.
|
188
|
-
# It converts charset of query value of fields into expected one.
|
189
|
-
def proc_query(field)
|
190
|
-
return unless field.query_value
|
191
|
-
field.query_value.map{|(name, val)|
|
192
|
-
[from_native_charset(name), from_native_charset(val.to_s)]
|
193
|
-
}
|
194
|
-
end
|
195
|
-
private :proc_query
|
196
|
-
|
197
|
-
def from_native_charset str
|
198
|
-
Mechanize::Util.from_native_charset(str, encoding, @ignore_encoding_error,
|
199
|
-
@mech && @mech.log)
|
200
|
-
end
|
201
|
-
private :from_native_charset
|
202
|
-
|
203
|
-
# This method builds an array of arrays that represent the query
|
204
|
-
# parameters to be used with this form. The return value can then
|
205
|
-
# be used to create a query string for this form.
|
206
|
-
def build_query(buttons = [])
|
207
|
-
query = []
|
208
|
-
@mech.log.info("form encoding: #{encoding}") if @mech && @mech.log
|
209
|
-
|
210
|
-
successful_controls = []
|
211
|
-
|
212
|
-
(fields + checkboxes).sort.each do |f|
|
213
|
-
case f
|
214
|
-
when Mechanize::Form::CheckBox
|
215
|
-
if f.checked
|
216
|
-
successful_controls << f
|
217
|
-
end
|
218
|
-
when Mechanize::Form::Field
|
219
|
-
successful_controls << f
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
radio_groups = {}
|
224
|
-
radiobuttons.each do |f|
|
225
|
-
fname = from_native_charset(f.name)
|
226
|
-
radio_groups[fname] ||= []
|
227
|
-
radio_groups[fname] << f
|
228
|
-
end
|
229
|
-
|
230
|
-
# take one radio button from each group
|
231
|
-
radio_groups.each_value do |g|
|
232
|
-
checked = g.select {|f| f.checked}
|
233
|
-
|
234
|
-
if checked.size == 1
|
235
|
-
f = checked.first
|
236
|
-
successful_controls << f
|
237
|
-
elsif checked.size > 1
|
238
|
-
raise Mechanize::Error,
|
239
|
-
"multiple radiobuttons are checked in the same group!"
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
@clicked_buttons.each { |b|
|
244
|
-
successful_controls << b
|
245
|
-
}
|
246
|
-
|
247
|
-
successful_controls.sort.each do |ctrl| # DOM order
|
248
|
-
qval = proc_query(ctrl)
|
249
|
-
query.push(*qval)
|
250
|
-
end
|
251
|
-
|
252
|
-
query
|
253
|
-
end
|
254
|
-
|
255
|
-
# This method adds a button to the query. If the form needs to be
|
256
|
-
# submitted with multiple buttons, pass each button to this method.
|
257
|
-
def add_button_to_query(button)
|
258
|
-
@clicked_buttons << button
|
259
|
-
end
|
260
|
-
|
261
|
-
# This method calculates the request data to be sent back to the server
|
262
|
-
# for this form, depending on if this is a regular post, get, or a
|
263
|
-
# multi-part post,
|
264
|
-
def request_data
|
265
|
-
query_params = build_query()
|
266
|
-
|
267
|
-
case @enctype.downcase
|
268
|
-
when /^multipart\/form-data/
|
269
|
-
boundary = rand_string(20)
|
270
|
-
@enctype = "multipart/form-data; boundary=#{boundary}"
|
271
|
-
|
272
|
-
params = query_params.map do |k,v|
|
273
|
-
param_to_multipart(k, v) if k
|
274
|
-
end.compact
|
275
|
-
|
276
|
-
params.concat @file_uploads.map { |f| file_to_multipart(f) }
|
277
|
-
|
278
|
-
params.map do |part|
|
279
|
-
part.force_encoding('ASCII-8BIT') if part.respond_to? :force_encoding
|
280
|
-
"--#{boundary}\r\n#{part}"
|
281
|
-
end.join('') +
|
282
|
-
"--#{boundary}--\r\n"
|
283
|
-
else
|
284
|
-
Mechanize::Util.build_query_string(query_params)
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
# Removes all fields with name +field_name+.
|
289
|
-
def delete_field!(field_name)
|
290
|
-
@fields.delete_if{ |f| f.name == field_name}
|
291
|
-
end
|
292
|
-
|
293
|
-
##
|
294
|
-
# :method: field_with(criteria)
|
295
|
-
#
|
296
|
-
# Find one field that matches +criteria+
|
297
|
-
# Example:
|
298
|
-
# form.field_with(:id => "exact_field_id").value = 'hello'
|
299
|
-
|
300
|
-
##
|
301
|
-
# :method: fields_with(criteria)
|
302
|
-
#
|
303
|
-
# Find all fields that match +criteria+
|
304
|
-
# Example:
|
305
|
-
# form.fields_with(:value => /foo/).each do |field|
|
306
|
-
# field.value = 'hello!'
|
307
|
-
# end
|
308
|
-
|
309
|
-
elements_with :field
|
310
|
-
|
311
|
-
##
|
312
|
-
# :method: button_with(criteria)
|
313
|
-
#
|
314
|
-
# Find one button that matches +criteria+
|
315
|
-
# Example:
|
316
|
-
# form.button_with(:value => /submit/).value = 'hello'
|
317
|
-
|
318
|
-
##
|
319
|
-
# :method: buttons_with(criteria)
|
320
|
-
#
|
321
|
-
# Find all buttons that match +criteria+
|
322
|
-
# Example:
|
323
|
-
# form.buttons_with(:value => /submit/).each do |button|
|
324
|
-
# button.value = 'hello!'
|
325
|
-
# end
|
326
|
-
|
327
|
-
elements_with :button
|
328
|
-
|
329
|
-
##
|
330
|
-
# :method: file_upload_with(criteria)
|
331
|
-
#
|
332
|
-
# Find one file upload field that matches +criteria+
|
333
|
-
# Example:
|
334
|
-
# form.file_upload_with(:file_name => /picture/).value = 'foo'
|
335
|
-
|
336
|
-
##
|
337
|
-
# :method: file_uploads_with(criteria)
|
338
|
-
#
|
339
|
-
# Find all file upload fields that match +criteria+
|
340
|
-
# Example:
|
341
|
-
# form.file_uploads_with(:file_name => /picutre/).each do |field|
|
342
|
-
# field.value = 'foo!'
|
343
|
-
# end
|
344
|
-
|
345
|
-
elements_with :file_upload
|
346
|
-
|
347
|
-
##
|
348
|
-
# :method: radiobutton_with(criteria)
|
349
|
-
#
|
350
|
-
# Find one radio button that matches +criteria+
|
351
|
-
# Example:
|
352
|
-
# form.radiobutton_with(:name => /woo/).check
|
353
|
-
|
354
|
-
##
|
355
|
-
# :method: radiobuttons_with(criteria)
|
356
|
-
#
|
357
|
-
# Find all radio buttons that match +criteria+
|
358
|
-
# Example:
|
359
|
-
# form.radiobuttons_with(:name => /woo/).each do |field|
|
360
|
-
# field.check
|
361
|
-
# end
|
362
|
-
|
363
|
-
elements_with :radiobutton
|
364
|
-
|
365
|
-
##
|
366
|
-
# :method: checkbox_with(criteria)
|
367
|
-
#
|
368
|
-
# Find one checkbox that matches +criteria+
|
369
|
-
# Example:
|
370
|
-
# form.checkbox_with(:name => /woo/).check
|
371
|
-
|
372
|
-
##
|
373
|
-
# :method: checkboxes_with(criteria)
|
374
|
-
#
|
375
|
-
# Find all checkboxes that match +criteria+
|
376
|
-
# Example:
|
377
|
-
# form.checkboxes_with(:name => /woo/).each do |field|
|
378
|
-
# field.check
|
379
|
-
# end
|
380
|
-
|
381
|
-
elements_with :checkbox, :checkboxes
|
382
|
-
|
383
|
-
def pretty_print(q) # :nodoc:
|
384
|
-
q.object_group(self) {
|
385
|
-
q.breakable; q.group(1, '{name', '}') { q.breakable; q.pp name }
|
386
|
-
q.breakable; q.group(1, '{method', '}') { q.breakable; q.pp method }
|
387
|
-
q.breakable; q.group(1, '{action', '}') { q.breakable; q.pp action }
|
388
|
-
q.breakable; q.group(1, '{fields', '}') {
|
389
|
-
fields.each do |field|
|
390
|
-
q.breakable
|
391
|
-
q.pp field
|
392
|
-
end
|
393
|
-
}
|
394
|
-
q.breakable; q.group(1, '{radiobuttons', '}') {
|
395
|
-
radiobuttons.each { |b| q.breakable; q.pp b }
|
396
|
-
}
|
397
|
-
q.breakable; q.group(1, '{checkboxes', '}') {
|
398
|
-
checkboxes.each { |b| q.breakable; q.pp b }
|
399
|
-
}
|
400
|
-
q.breakable; q.group(1, '{file_uploads', '}') {
|
401
|
-
file_uploads.each { |b| q.breakable; q.pp b }
|
402
|
-
}
|
403
|
-
q.breakable; q.group(1, '{buttons', '}') {
|
404
|
-
buttons.each { |b| q.breakable; q.pp b }
|
405
|
-
}
|
406
|
-
}
|
407
|
-
end
|
408
|
-
|
409
|
-
alias inspect pretty_inspect # :nodoc:
|
410
|
-
|
411
|
-
private
|
412
|
-
|
413
|
-
def parse
|
414
|
-
@fields = []
|
415
|
-
@buttons = []
|
416
|
-
@file_uploads = []
|
417
|
-
@radiobuttons = []
|
418
|
-
@checkboxes = []
|
419
|
-
|
420
|
-
# Find all input tags
|
421
|
-
form_node.search('input').each do |node|
|
422
|
-
type = (node['type'] || 'text').downcase
|
423
|
-
name = node['name']
|
424
|
-
next if name.nil? && !%w[submit button image].include?(type)
|
425
|
-
case type
|
426
|
-
when 'radio'
|
427
|
-
@radiobuttons << RadioButton.new(node, self)
|
428
|
-
when 'checkbox'
|
429
|
-
@checkboxes << CheckBox.new(node, self)
|
430
|
-
when 'file'
|
431
|
-
@file_uploads << FileUpload.new(node, nil)
|
432
|
-
when 'submit'
|
433
|
-
@buttons << Submit.new(node)
|
434
|
-
when 'button'
|
435
|
-
@buttons << Button.new(node)
|
436
|
-
when 'reset'
|
437
|
-
@buttons << Reset.new(node)
|
438
|
-
when 'image'
|
439
|
-
@buttons << ImageButton.new(node)
|
440
|
-
when 'hidden'
|
441
|
-
@fields << Hidden.new(node, node['value'] || '')
|
442
|
-
when 'text'
|
443
|
-
@fields << Text.new(node, node['value'] || '')
|
444
|
-
when 'textarea'
|
445
|
-
@fields << Textarea.new(node, node['value'] || '')
|
446
|
-
else
|
447
|
-
@fields << Field.new(node, node['value'] || '')
|
448
|
-
end
|
449
|
-
end
|
450
|
-
|
451
|
-
# Find all textarea tags
|
452
|
-
form_node.search('textarea').each do |node|
|
453
|
-
next unless node['name']
|
454
|
-
@fields << Textarea.new(node, node.inner_text)
|
455
|
-
end
|
456
|
-
|
457
|
-
# Find all select tags
|
458
|
-
form_node.search('select').each do |node|
|
459
|
-
next unless node['name']
|
460
|
-
if node.has_attribute? 'multiple'
|
461
|
-
@fields << MultiSelectList.new(node)
|
462
|
-
else
|
463
|
-
@fields << SelectList.new(node)
|
464
|
-
end
|
465
|
-
end
|
466
|
-
|
467
|
-
# Find all submit button tags
|
468
|
-
# FIXME: what can I do with the reset buttons?
|
469
|
-
form_node.search('button').each do |node|
|
470
|
-
type = (node['type'] || 'submit').downcase
|
471
|
-
next if type == 'reset'
|
472
|
-
@buttons << Button.new(node)
|
473
|
-
end
|
474
|
-
|
475
|
-
# Find all keygen tags
|
476
|
-
form_node.search('keygen').each do |node|
|
477
|
-
@fields << Keygen.new(node, node['value'] || '')
|
478
|
-
end
|
479
|
-
end
|
480
|
-
|
481
|
-
def rand_string(len = 10)
|
482
|
-
chars = ("a".."z").to_a + ("A".."Z").to_a
|
483
|
-
string = ""
|
484
|
-
1.upto(len) { |i| string << chars[rand(chars.size-1)] }
|
485
|
-
string
|
486
|
-
end
|
487
|
-
|
488
|
-
def mime_value_quote(str)
|
489
|
-
str.gsub(/(["\r\\])/){|s| '\\' + s}
|
490
|
-
end
|
491
|
-
|
492
|
-
def param_to_multipart(name, value)
|
493
|
-
return "Content-Disposition: form-data; name=\"" +
|
494
|
-
"#{mime_value_quote(name)}\"\r\n" +
|
495
|
-
"\r\n#{value}\r\n"
|
496
|
-
end
|
497
|
-
|
498
|
-
def file_to_multipart(file)
|
499
|
-
file_name = file.file_name ? ::File.basename(file.file_name) : ''
|
500
|
-
body = "Content-Disposition: form-data; name=\"" +
|
501
|
-
"#{mime_value_quote(file.name)}\"; " +
|
502
|
-
"filename=\"#{mime_value_quote(file_name)}\"\r\n" +
|
503
|
-
"Content-Transfer-Encoding: binary\r\n"
|
504
|
-
|
505
|
-
if file.file_data.nil? and file.file_name
|
506
|
-
file.file_data = open(file.file_name, "rb") { |f| f.read }
|
507
|
-
file.mime_type =
|
508
|
-
WEBrick::HTTPUtils.mime_type(file.file_name,
|
509
|
-
WEBrick::HTTPUtils::DefaultMimeTypes)
|
510
|
-
end
|
511
|
-
|
512
|
-
if file.mime_type
|
513
|
-
body << "Content-Type: #{file.mime_type}\r\n"
|
514
|
-
end
|
515
|
-
|
516
|
-
body <<
|
517
|
-
if file.file_data.respond_to? :read
|
518
|
-
"\r\n#{file.file_data.read}\r\n"
|
519
|
-
else
|
520
|
-
"\r\n#{file.file_data}\r\n"
|
521
|
-
end
|
522
|
-
|
523
|
-
body
|
524
|
-
end
|
525
|
-
|
526
|
-
end
|
527
|
-
|
528
|
-
require 'mechanize/form/field'
|
529
|
-
require 'mechanize/form/button'
|
530
|
-
require 'mechanize/form/hidden'
|
531
|
-
require 'mechanize/form/text'
|
532
|
-
require 'mechanize/form/textarea'
|
533
|
-
require 'mechanize/form/submit'
|
534
|
-
require 'mechanize/form/reset'
|
535
|
-
require 'mechanize/form/file_upload'
|
536
|
-
require 'mechanize/form/keygen'
|
537
|
-
require 'mechanize/form/image_button'
|
538
|
-
require 'mechanize/form/multi_select_list'
|
539
|
-
require 'mechanize/form/option'
|
540
|
-
require 'mechanize/form/radio_button'
|
541
|
-
require 'mechanize/form/check_box'
|
542
|
-
require 'mechanize/form/select_list'
|
543
|
-
|