mkuklis-webrat 0.5.1

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.
Files changed (213) hide show
  1. data/.document +4 -0
  2. data/.gitignore +15 -0
  3. data/History.txt +413 -0
  4. data/MIT-LICENSE.txt +19 -0
  5. data/README.rdoc +85 -0
  6. data/Rakefile +188 -0
  7. data/VERSION +1 -0
  8. data/install.rb +1 -0
  9. data/lib/webrat/adapters/mechanize.rb +78 -0
  10. data/lib/webrat/adapters/merb.rb +11 -0
  11. data/lib/webrat/adapters/rack.rb +25 -0
  12. data/lib/webrat/adapters/rails.rb +81 -0
  13. data/lib/webrat/adapters/sinatra.rb +9 -0
  14. data/lib/webrat/core/configuration.rb +92 -0
  15. data/lib/webrat/core/elements/area.rb +31 -0
  16. data/lib/webrat/core/elements/element.rb +33 -0
  17. data/lib/webrat/core/elements/field.rb +487 -0
  18. data/lib/webrat/core/elements/form.rb +103 -0
  19. data/lib/webrat/core/elements/label.rb +31 -0
  20. data/lib/webrat/core/elements/link.rb +93 -0
  21. data/lib/webrat/core/elements/select_option.rb +48 -0
  22. data/lib/webrat/core/locators/area_locator.rb +38 -0
  23. data/lib/webrat/core/locators/button_locator.rb +54 -0
  24. data/lib/webrat/core/locators/field_by_id_locator.rb +37 -0
  25. data/lib/webrat/core/locators/field_labeled_locator.rb +56 -0
  26. data/lib/webrat/core/locators/field_locator.rb +25 -0
  27. data/lib/webrat/core/locators/field_named_locator.rb +41 -0
  28. data/lib/webrat/core/locators/form_locator.rb +19 -0
  29. data/lib/webrat/core/locators/label_locator.rb +34 -0
  30. data/lib/webrat/core/locators/link_locator.rb +74 -0
  31. data/lib/webrat/core/locators/locator.rb +20 -0
  32. data/lib/webrat/core/locators/select_option_locator.rb +59 -0
  33. data/lib/webrat/core/locators.rb +20 -0
  34. data/lib/webrat/core/logging.rb +23 -0
  35. data/lib/webrat/core/matchers/have_content.rb +68 -0
  36. data/lib/webrat/core/matchers/have_selector.rb +74 -0
  37. data/lib/webrat/core/matchers/have_tag.rb +21 -0
  38. data/lib/webrat/core/matchers/have_xpath.rb +122 -0
  39. data/lib/webrat/core/matchers.rb +4 -0
  40. data/lib/webrat/core/methods.rb +64 -0
  41. data/lib/webrat/core/mime.rb +18 -0
  42. data/lib/webrat/core/save_and_open_page.rb +48 -0
  43. data/lib/webrat/core/scope.rb +365 -0
  44. data/lib/webrat/core/session.rb +306 -0
  45. data/lib/webrat/core/xml.rb +72 -0
  46. data/lib/webrat/core.rb +13 -0
  47. data/lib/webrat/core_extensions/blank.rb +58 -0
  48. data/lib/webrat/core_extensions/deprecate.rb +8 -0
  49. data/lib/webrat/core_extensions/detect_mapped.rb +12 -0
  50. data/lib/webrat/core_extensions/meta_class.rb +6 -0
  51. data/lib/webrat/core_extensions/nil_to_param.rb +5 -0
  52. data/lib/webrat/core_extensions/tcp_socket.rb +27 -0
  53. data/lib/webrat/integrations/merb.rb +10 -0
  54. data/lib/webrat/integrations/rails.rb +25 -0
  55. data/lib/webrat/integrations/rspec-rails.rb +10 -0
  56. data/lib/webrat/integrations/selenium.rb +11 -0
  57. data/lib/webrat/merb.rb +9 -0
  58. data/lib/webrat/rspec-rails.rb +2 -0
  59. data/lib/webrat/selenium/application_server_factory.rb +40 -0
  60. data/lib/webrat/selenium/application_servers/base.rb +54 -0
  61. data/lib/webrat/selenium/application_servers/external.rb +26 -0
  62. data/lib/webrat/selenium/application_servers/merb.rb +50 -0
  63. data/lib/webrat/selenium/application_servers/rails.rb +67 -0
  64. data/lib/webrat/selenium/application_servers/sinatra.rb +37 -0
  65. data/lib/webrat/selenium/application_servers.rb +5 -0
  66. data/lib/webrat/selenium/location_strategy_javascript/button.js +19 -0
  67. data/lib/webrat/selenium/location_strategy_javascript/label.js +42 -0
  68. data/lib/webrat/selenium/location_strategy_javascript/webrat.js +6 -0
  69. data/lib/webrat/selenium/location_strategy_javascript/webratlink.js +32 -0
  70. data/lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js +15 -0
  71. data/lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js +5 -0
  72. data/lib/webrat/selenium/matchers/have_content.rb +66 -0
  73. data/lib/webrat/selenium/matchers/have_selector.rb +49 -0
  74. data/lib/webrat/selenium/matchers/have_tag.rb +72 -0
  75. data/lib/webrat/selenium/matchers/have_xpath.rb +45 -0
  76. data/lib/webrat/selenium/matchers.rb +4 -0
  77. data/lib/webrat/selenium/selenium_extensions.js +6 -0
  78. data/lib/webrat/selenium/selenium_rc_server.rb +86 -0
  79. data/lib/webrat/selenium/selenium_session.rb +272 -0
  80. data/lib/webrat/selenium/silence_stream.rb +18 -0
  81. data/lib/webrat/selenium.rb +70 -0
  82. data/lib/webrat.rb +18 -0
  83. data/spec/fakes/test_adapter.rb +37 -0
  84. data/spec/integration/mechanize/Rakefile +7 -0
  85. data/spec/integration/mechanize/config.ru +2 -0
  86. data/spec/integration/mechanize/sample_app.rb +20 -0
  87. data/spec/integration/mechanize/spec/mechanize_spec.rb +22 -0
  88. data/spec/integration/mechanize/spec/spec_helper.rb +27 -0
  89. data/spec/integration/merb/.gitignore +21 -0
  90. data/spec/integration/merb/Rakefile +35 -0
  91. data/spec/integration/merb/app/controllers/application.rb +2 -0
  92. data/spec/integration/merb/app/controllers/exceptions.rb +13 -0
  93. data/spec/integration/merb/app/controllers/testing.rb +27 -0
  94. data/spec/integration/merb/app/views/exceptions/not_acceptable.html.erb +63 -0
  95. data/spec/integration/merb/app/views/exceptions/not_found.html.erb +47 -0
  96. data/spec/integration/merb/app/views/layout/application.html.erb +12 -0
  97. data/spec/integration/merb/app/views/testing/show_form.html.erb +27 -0
  98. data/spec/integration/merb/app/views/testing/upload.html.erb +9 -0
  99. data/spec/integration/merb/config/environments/development.rb +15 -0
  100. data/spec/integration/merb/config/environments/rake.rb +11 -0
  101. data/spec/integration/merb/config/environments/test.rb +14 -0
  102. data/spec/integration/merb/config/init.rb +25 -0
  103. data/spec/integration/merb/config/rack.rb +11 -0
  104. data/spec/integration/merb/config/router.rb +34 -0
  105. data/spec/integration/merb/spec/spec.opts +1 -0
  106. data/spec/integration/merb/spec/spec_helper.rb +26 -0
  107. data/spec/integration/merb/spec/webrat_spec.rb +39 -0
  108. data/spec/integration/merb/tasks/merb.thor/app_script.rb +31 -0
  109. data/spec/integration/merb/tasks/merb.thor/common.rb +64 -0
  110. data/spec/integration/merb/tasks/merb.thor/gem_ext.rb +124 -0
  111. data/spec/integration/merb/tasks/merb.thor/main.thor +150 -0
  112. data/spec/integration/merb/tasks/merb.thor/ops.rb +93 -0
  113. data/spec/integration/merb/tasks/merb.thor/utils.rb +40 -0
  114. data/spec/integration/rack/Rakefile +5 -0
  115. data/spec/integration/rack/app.rb +89 -0
  116. data/spec/integration/rack/test/helper.rb +21 -0
  117. data/spec/integration/rack/test/webrat_rack_test.rb +73 -0
  118. data/spec/integration/rails/.gitignore +3 -0
  119. data/spec/integration/rails/Rakefile +30 -0
  120. data/spec/integration/rails/app/controllers/application.rb +15 -0
  121. data/spec/integration/rails/app/controllers/buttons_controller.rb +7 -0
  122. data/spec/integration/rails/app/controllers/fields_controller.rb +4 -0
  123. data/spec/integration/rails/app/controllers/links_controller.rb +7 -0
  124. data/spec/integration/rails/app/controllers/webrat_controller.rb +46 -0
  125. data/spec/integration/rails/app/helpers/buttons_helper.rb +2 -0
  126. data/spec/integration/rails/app/helpers/fields_helper.rb +2 -0
  127. data/spec/integration/rails/app/helpers/links_helper.rb +2 -0
  128. data/spec/integration/rails/app/views/buttons/show.html.erb +11 -0
  129. data/spec/integration/rails/app/views/fields/show.html.erb +9 -0
  130. data/spec/integration/rails/app/views/links/show.html.erb +5 -0
  131. data/spec/integration/rails/app/views/webrat/before_redirect_form.html.erb +4 -0
  132. data/spec/integration/rails/app/views/webrat/buttons.html.erb +11 -0
  133. data/spec/integration/rails/app/views/webrat/form.html.erb +28 -0
  134. data/spec/integration/rails/app/views/webrat/within.html.erb +3 -0
  135. data/spec/integration/rails/config/boot.rb +109 -0
  136. data/spec/integration/rails/config/environment.rb +12 -0
  137. data/spec/integration/rails/config/environments/development.rb +17 -0
  138. data/spec/integration/rails/config/environments/selenium.rb +22 -0
  139. data/spec/integration/rails/config/environments/test.rb +22 -0
  140. data/spec/integration/rails/config/initializers/inflections.rb +10 -0
  141. data/spec/integration/rails/config/initializers/mime_types.rb +5 -0
  142. data/spec/integration/rails/config/initializers/new_rails_defaults.rb +17 -0
  143. data/spec/integration/rails/config/locales/en.yml +5 -0
  144. data/spec/integration/rails/config/routes.rb +19 -0
  145. data/spec/integration/rails/public/404.html +30 -0
  146. data/spec/integration/rails/public/422.html +30 -0
  147. data/spec/integration/rails/public/500.html +33 -0
  148. data/spec/integration/rails/script/about +4 -0
  149. data/spec/integration/rails/script/console +3 -0
  150. data/spec/integration/rails/script/dbconsole +3 -0
  151. data/spec/integration/rails/script/destroy +3 -0
  152. data/spec/integration/rails/script/generate +3 -0
  153. data/spec/integration/rails/script/performance/benchmarker +3 -0
  154. data/spec/integration/rails/script/performance/profiler +3 -0
  155. data/spec/integration/rails/script/performance/request +3 -0
  156. data/spec/integration/rails/script/plugin +3 -0
  157. data/spec/integration/rails/script/process/inspector +3 -0
  158. data/spec/integration/rails/script/process/reaper +3 -0
  159. data/spec/integration/rails/script/process/spawner +3 -0
  160. data/spec/integration/rails/script/runner +3 -0
  161. data/spec/integration/rails/script/server +3 -0
  162. data/spec/integration/rails/test/integration/button_click_test.rb +80 -0
  163. data/spec/integration/rails/test/integration/fill_in_test.rb +24 -0
  164. data/spec/integration/rails/test/integration/link_click_test.rb +27 -0
  165. data/spec/integration/rails/test/integration/webrat_test.rb +122 -0
  166. data/spec/integration/rails/test/test_helper.rb +26 -0
  167. data/spec/integration/sinatra/Rakefile +5 -0
  168. data/spec/integration/sinatra/classic_app.rb +64 -0
  169. data/spec/integration/sinatra/modular_app.rb +16 -0
  170. data/spec/integration/sinatra/test/classic_app_test.rb +37 -0
  171. data/spec/integration/sinatra/test/modular_app_test.rb +18 -0
  172. data/spec/integration/sinatra/test/test_helper.rb +17 -0
  173. data/spec/private/core/configuration_spec.rb +87 -0
  174. data/spec/private/core/field_spec.rb +85 -0
  175. data/spec/private/core/link_spec.rb +24 -0
  176. data/spec/private/core/session_spec.rb +200 -0
  177. data/spec/private/mechanize/mechanize_adapter_spec.rb +73 -0
  178. data/spec/private/nokogiri_spec.rb +77 -0
  179. data/spec/private/rails/attaches_file_spec.rb +81 -0
  180. data/spec/private/rails/rails_adapter_spec.rb +86 -0
  181. data/spec/private/selenium/application_servers/rails_spec.rb +26 -0
  182. data/spec/public/basic_auth_spec.rb +24 -0
  183. data/spec/public/check_spec.rb +191 -0
  184. data/spec/public/choose_spec.rb +118 -0
  185. data/spec/public/click_area_spec.rb +106 -0
  186. data/spec/public/click_button_spec.rb +494 -0
  187. data/spec/public/click_link_spec.rb +511 -0
  188. data/spec/public/fill_in_spec.rb +224 -0
  189. data/spec/public/locators/field_by_xpath_spec.rb +19 -0
  190. data/spec/public/locators/field_labeled_spec.rb +172 -0
  191. data/spec/public/locators/field_with_id_spec.rb +16 -0
  192. data/spec/public/matchers/contain_spec.rb +114 -0
  193. data/spec/public/matchers/have_selector_spec.rb +146 -0
  194. data/spec/public/matchers/have_tag_spec.rb +39 -0
  195. data/spec/public/matchers/have_xpath_spec.rb +136 -0
  196. data/spec/public/reload_spec.rb +10 -0
  197. data/spec/public/save_and_open_spec.rb +70 -0
  198. data/spec/public/select_date_spec.rb +112 -0
  199. data/spec/public/select_datetime_spec.rb +137 -0
  200. data/spec/public/select_spec.rb +455 -0
  201. data/spec/public/select_time_spec.rb +100 -0
  202. data/spec/public/selenium/application_server_factory_spec.rb +49 -0
  203. data/spec/public/selenium/application_servers/external_spec.rb +12 -0
  204. data/spec/public/selenium/selenium_session_spec.rb +37 -0
  205. data/spec/public/set_hidden_field_spec.rb +5 -0
  206. data/spec/public/submit_form_spec.rb +5 -0
  207. data/spec/public/visit_spec.rb +58 -0
  208. data/spec/public/within_spec.rb +177 -0
  209. data/spec/rcov.opts +1 -0
  210. data/spec/spec.opts +2 -0
  211. data/spec/spec_helper.rb +54 -0
  212. data/vendor/selenium-server.jar +0 -0
  213. metadata +409 -0
@@ -0,0 +1,487 @@
1
+ require "cgi"
2
+ require "webrat/core_extensions/blank"
3
+ require "webrat/core_extensions/nil_to_param"
4
+
5
+ require "webrat/core/elements/element"
6
+
7
+ module Webrat
8
+ # Raised when Webrat is asked to manipulate a disabled form field
9
+ class DisabledFieldError < WebratError
10
+ end
11
+
12
+ class Field < Element #:nodoc:
13
+ attr_reader :value
14
+
15
+ def self.xpath_search
16
+ [".//button", ".//input", ".//textarea", ".//select"]
17
+ end
18
+
19
+ def self.xpath_search_excluding_hidden
20
+ [".//button", ".//input[ @type != 'hidden']", ".//textarea", ".//select"]
21
+ end
22
+
23
+ def self.field_classes
24
+ @field_classes || []
25
+ end
26
+
27
+ def self.inherited(klass)
28
+ @field_classes ||= []
29
+ @field_classes << klass
30
+ # raise args.inspect
31
+ end
32
+
33
+ def self.load(session, element)
34
+ return nil if element.nil?
35
+ session.elements[element.path] ||= field_class(element).new(session, element)
36
+ end
37
+
38
+ def self.field_class(element)
39
+ case element.name
40
+ when "button" then ButtonField
41
+ when "select"
42
+ if element.attributes["multiple"].nil?
43
+ SelectField
44
+ else
45
+ MultipleSelectField
46
+ end
47
+ when "textarea" then TextareaField
48
+ else
49
+ case element["type"]
50
+ when "checkbox" then CheckboxField
51
+ when "hidden" then HiddenField
52
+ when "radio" then RadioField
53
+ when "password" then PasswordField
54
+ when "file" then FileField
55
+ when "reset" then ResetField
56
+ when "submit" then ButtonField
57
+ when "button" then ButtonField
58
+ when "image" then ButtonField
59
+ else TextField
60
+ end
61
+ end
62
+ end
63
+
64
+ def initialize(*args)
65
+ super
66
+ @value = default_value
67
+ end
68
+
69
+ def label_text
70
+ return nil if labels.empty?
71
+ labels.first.text
72
+ end
73
+
74
+ def id
75
+ @element["id"]
76
+ end
77
+
78
+ def disabled?
79
+ @element.attributes.has_key?("disabled") && @element["disabled"] != 'false'
80
+ end
81
+
82
+ def raise_error_if_disabled
83
+ return unless disabled?
84
+ raise DisabledFieldError.new("Cannot interact with disabled form element (#{self})")
85
+ end
86
+
87
+ def to_param
88
+ return nil if disabled?
89
+
90
+ params = case Webrat.configuration.mode
91
+ when :rails
92
+ parse_rails_request_params("#{name}=#{escaped_value}")
93
+ when :merb
94
+ ::Merb::Parse.query("#{name}=#{escaped_value}")
95
+ else
96
+ { name => [*@value].first.to_s }
97
+ end
98
+
99
+ unescape_params(params)
100
+ end
101
+
102
+ def set(value)
103
+ @value = value
104
+ end
105
+
106
+ def unset
107
+ @value = default_value
108
+ end
109
+
110
+ protected
111
+
112
+ def parse_rails_request_params(params)
113
+ if defined?(ActionController::AbstractRequest)
114
+ ActionController::AbstractRequest.parse_query_parameters(params)
115
+ elsif defined?(ActionController::UrlEncodedPairParser)
116
+ # For Rails > 2.2
117
+ ActionController::UrlEncodedPairParser.parse_query_parameters(params)
118
+ else
119
+ # For Rails > 2.3
120
+ Rack::Utils.parse_nested_query(params)
121
+ end
122
+ end
123
+
124
+ def form
125
+ Form.load(@session, form_element)
126
+ end
127
+
128
+ def form_element
129
+ parent = @element.parent
130
+
131
+ while parent.respond_to?(:parent)
132
+ return parent if parent.name == 'form'
133
+ parent = parent.parent
134
+ end
135
+ end
136
+
137
+ def name
138
+ @element["name"]
139
+ end
140
+
141
+ def escaped_value
142
+ CGI.escape(@value.to_s)
143
+ end
144
+
145
+ # Because we have to escape it before sending it to the above case statement,
146
+ # we have to make sure we unescape each value when it gets back so assertions
147
+ # involving characters like <, >, and & work as expected
148
+ def unescape_params(params)
149
+ case params.class.name
150
+ when 'Hash', 'Mash'
151
+ params.each { |key,value| params[key] = unescape_params(value) }
152
+ params
153
+ when 'Array'
154
+ params.collect { |value| unescape_params(value) }
155
+ else
156
+ CGI.unescapeHTML(params)
157
+ end
158
+ end
159
+
160
+ def labels
161
+ @labels ||= label_elements.map do |element|
162
+ Label.load(@session, element)
163
+ end
164
+ end
165
+
166
+ def label_elements
167
+ return @label_elements unless @label_elements.nil?
168
+ @label_elements = []
169
+
170
+ parent = @element.parent
171
+ while parent.respond_to?(:parent)
172
+ if parent.name == 'label'
173
+ @label_elements.push parent
174
+ break
175
+ end
176
+ parent = parent.parent
177
+ end
178
+
179
+ unless id.blank?
180
+ @label_elements += form.element.xpath(".//label[@for = '#{id}']")
181
+ end
182
+
183
+ @label_elements
184
+ end
185
+
186
+ def default_value
187
+ @element["value"]
188
+ end
189
+
190
+ def replace_param_value(params, oval, nval)
191
+ output = Hash.new
192
+ params.each do |key, value|
193
+ case value
194
+ when Hash
195
+ value = replace_param_value(value, oval, nval)
196
+ when Array
197
+ value = value.map { |o| o == oval ? nval : oval }
198
+ when oval
199
+ value = nval
200
+ end
201
+ output[key] = value
202
+ end
203
+ output
204
+ end
205
+ end
206
+
207
+ class ButtonField < Field #:nodoc:
208
+
209
+ def self.xpath_search
210
+ [".//button", ".//input[@type = 'submit']", ".//input[@type = 'button']", ".//input[@type = 'image']"]
211
+ end
212
+
213
+ def to_param
214
+ return nil if @value.nil?
215
+ super
216
+ end
217
+
218
+ def default_value
219
+ nil
220
+ end
221
+
222
+ def click
223
+ raise_error_if_disabled
224
+ set(@element["value"]) unless @element["name"].blank?
225
+ form.submit
226
+ end
227
+
228
+ end
229
+
230
+ class HiddenField < Field #:nodoc:
231
+
232
+ def self.xpath_search
233
+ ".//input[@type = 'hidden']"
234
+ end
235
+
236
+ def to_param
237
+ if collection_name?
238
+ super
239
+ else
240
+ checkbox_with_same_name = form.field_named(name, CheckboxField)
241
+
242
+ if checkbox_with_same_name.to_param.blank?
243
+ super
244
+ else
245
+ nil
246
+ end
247
+ end
248
+ end
249
+
250
+ protected
251
+
252
+ def collection_name?
253
+ name =~ /\[\]/
254
+ end
255
+
256
+ end
257
+
258
+ class CheckboxField < Field #:nodoc:
259
+
260
+ def self.xpath_search
261
+ ".//input[@type = 'checkbox']"
262
+ end
263
+
264
+ def to_param
265
+ return nil if @value.nil?
266
+ super
267
+ end
268
+
269
+ def check
270
+ raise_error_if_disabled
271
+ set(@element["value"] || "on")
272
+ end
273
+
274
+ def checked?
275
+ @element["checked"] == "checked"
276
+ end
277
+
278
+ def uncheck
279
+ raise_error_if_disabled
280
+ set(nil)
281
+ end
282
+
283
+ protected
284
+
285
+ def default_value
286
+ if @element["checked"] == "checked"
287
+ @element["value"] || "on"
288
+ else
289
+ nil
290
+ end
291
+ end
292
+
293
+ end
294
+
295
+ class PasswordField < Field #:nodoc:
296
+
297
+ def self.xpath_search
298
+ ".//input[@type = 'password']"
299
+ end
300
+
301
+ end
302
+
303
+ class RadioField < Field #:nodoc:
304
+
305
+ def self.xpath_search
306
+ ".//input[@type = 'radio']"
307
+ end
308
+
309
+ def to_param
310
+ return nil if @value.nil?
311
+ super
312
+ end
313
+
314
+ def choose
315
+ raise_error_if_disabled
316
+ other_options.each do |option|
317
+ option.set(nil)
318
+ end
319
+
320
+ set(@element["value"] || "on")
321
+ end
322
+
323
+ def checked?
324
+ @element["checked"] == "checked"
325
+ end
326
+
327
+ protected
328
+
329
+ def other_options
330
+ form.fields.select { |f| f.name == name }
331
+ end
332
+
333
+ def default_value
334
+ if @element["checked"] == "checked"
335
+ @element["value"] || "on"
336
+ else
337
+ nil
338
+ end
339
+ end
340
+
341
+ end
342
+
343
+ class TextareaField < Field #:nodoc:
344
+
345
+ def self.xpath_search
346
+ ".//textarea"
347
+ end
348
+
349
+ protected
350
+
351
+ def default_value
352
+ @element.inner_html
353
+ end
354
+
355
+ end
356
+
357
+ class FileField < Field #:nodoc:
358
+
359
+ def self.xpath_search
360
+ ".//input[@type = 'file']"
361
+ end
362
+
363
+ attr_accessor :content_type
364
+
365
+ def set(value, content_type = nil)
366
+ super(value)
367
+ @content_type = content_type
368
+ end
369
+
370
+ def to_param
371
+ if @value.nil?
372
+ super
373
+ else
374
+ replace_param_value(super, @value, test_uploaded_file)
375
+ end
376
+ end
377
+
378
+ protected
379
+
380
+ def test_uploaded_file
381
+ case Webrat.configuration.mode
382
+ when :rails
383
+ if content_type
384
+ ActionController::TestUploadedFile.new(@value, content_type)
385
+ else
386
+ ActionController::TestUploadedFile.new(@value)
387
+ end
388
+ when :rack, :merb
389
+ Rack::Test::UploadedFile.new(@value, content_type)
390
+ end
391
+ end
392
+
393
+ end
394
+
395
+ class TextField < Field #:nodoc:
396
+ def self.xpath_search
397
+ [".//input[@type = 'text']", ".//input[not(@type)]"]
398
+ end
399
+ end
400
+
401
+ class ResetField < Field #:nodoc:
402
+ def self.xpath_search
403
+ [".//input[@type = 'reset']"]
404
+ end
405
+ end
406
+
407
+ class SelectField < Field #:nodoc:
408
+
409
+ def self.xpath_search
410
+ [".//select[not(@multiple)]"]
411
+ end
412
+
413
+ def options
414
+ @options ||= SelectOption.load_all(@session, @element)
415
+ end
416
+
417
+ def unset(value)
418
+ @value = nil
419
+ end
420
+
421
+ protected
422
+
423
+ def default_value
424
+ selected_options = @element.xpath(".//option[@selected = 'selected']")
425
+ selected_options = @element.xpath(".//option[position() = 1]") if selected_options.empty?
426
+
427
+ selected_options.map do |option|
428
+ return "" if option.nil?
429
+ option["value"] || option.inner_html
430
+ end.uniq.first
431
+ end
432
+
433
+ end
434
+
435
+ class MultipleSelectField < Field #:nodoc:
436
+
437
+ def self.xpath_search
438
+ [".//select[@multiple='multiple']"]
439
+ end
440
+
441
+ def options
442
+ @options ||= SelectOption.load_all(@session, @element)
443
+ end
444
+
445
+ def set(value)
446
+ @value << value
447
+ end
448
+
449
+ def unset(value)
450
+ @value.delete(value)
451
+ end
452
+
453
+ # We have to overide how the uri string is formed when dealing with multiples
454
+ # Where normally a select field might produce name=value with a multiple,
455
+ # we need to form something like name[]=value1&name[]=value2
456
+ def to_param
457
+ return nil if disabled?
458
+
459
+ uri_string = @value.collect {|value| "#{name}=#{CGI.escape(value)}"}.join("&")
460
+ params = case Webrat.configuration.mode
461
+ when :rails
462
+ parse_rails_request_params(uri_string)
463
+ when :merb
464
+ ::Merb::Parse.query(uri_string)
465
+ else
466
+ { name => @value }
467
+ end
468
+
469
+ unescape_params(params)
470
+ end
471
+
472
+ protected
473
+
474
+ # Overwrite SelectField definition because we don't want to select the first option
475
+ # (mutliples don't select the first option unlike their non multiple versions)
476
+ def default_value
477
+ selected_options = @element.xpath(".//option[@selected = 'selected']")
478
+
479
+ selected_options.map do |option|
480
+ return "" if option.nil?
481
+ option["value"] || option.inner_html
482
+ end.uniq
483
+ end
484
+
485
+ end
486
+
487
+ end
@@ -0,0 +1,103 @@
1
+ require "webrat/core/elements/field"
2
+ require "webrat/core_extensions/blank"
3
+
4
+ require "webrat/core/elements/element"
5
+ require "webrat/core/locators/field_named_locator"
6
+
7
+ module Webrat
8
+ class Form < Element #:nodoc:
9
+ attr_reader :element
10
+
11
+ def self.xpath_search
12
+ [".//form"]
13
+ end
14
+
15
+ def fields
16
+ @fields ||= Field.load_all(@session, @element)
17
+ end
18
+
19
+ def submit
20
+ @session.request_page(form_action, form_method, params)
21
+ end
22
+
23
+ def field_named(name, *field_types)
24
+ Webrat::Locators::FieldNamedLocator.new(@session, dom, name, *field_types).locate
25
+ end
26
+
27
+ protected
28
+
29
+ def dom
30
+ @session.dom.xpath(path).first
31
+ end
32
+
33
+ def fields_by_type(field_types)
34
+ if field_types.any?
35
+ fields.select { |f| field_types.include?(f.class) }
36
+ else
37
+ fields
38
+ end
39
+ end
40
+
41
+ def params
42
+ all_params = {}
43
+
44
+ fields.each do |field|
45
+ next if field.to_param.nil?
46
+ merge(all_params, field.to_param)
47
+ end
48
+
49
+ all_params
50
+ end
51
+
52
+ def form_method
53
+ @element["method"].blank? ? :get : @element["method"].downcase
54
+ end
55
+
56
+ def form_action
57
+ @element["action"].blank? ? @session.current_url : @element["action"]
58
+ end
59
+
60
+ def merge(all_params, new_param)
61
+ new_param.each do |key, value|
62
+ case all_params[key]
63
+ when *hash_classes
64
+ merge_hash_values(all_params[key], value)
65
+ when Array
66
+ all_params[key] += value
67
+ else
68
+ all_params[key] = value
69
+ end
70
+ end
71
+ end
72
+
73
+ def merge_hash_values(a, b) # :nodoc:
74
+ a.keys.each do |k|
75
+ if b.has_key?(k)
76
+ case [a[k], b[k]].map{|value| value.class}
77
+ when *hash_classes.zip(hash_classes)
78
+ a[k] = merge_hash_values(a[k], b[k])
79
+ b.delete(k)
80
+ when [Array, Array]
81
+ a[k] += b[k]
82
+ b.delete(k)
83
+ end
84
+ end
85
+ end
86
+ a.merge!(b)
87
+ end
88
+
89
+ def hash_classes
90
+ klasses = [Hash]
91
+
92
+ case Webrat.configuration.mode
93
+ when :rails
94
+ klasses << HashWithIndifferentAccess
95
+ when :merb
96
+ klasses << Mash
97
+ end
98
+
99
+ klasses
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,31 @@
1
+ require "webrat/core/elements/element"
2
+
3
+ module Webrat
4
+ class Label < Element #:nodoc:
5
+
6
+ attr_reader :element
7
+
8
+ def self.xpath_search
9
+ [".//label"]
10
+ end
11
+
12
+ def for_id
13
+ @element["for"]
14
+ end
15
+
16
+ def field
17
+ Field.load(@session, field_element)
18
+ end
19
+
20
+ protected
21
+
22
+ def field_element
23
+ if for_id.blank?
24
+ @element.xpath(*Field.xpath_search_excluding_hidden).first
25
+ else
26
+ @session.current_dom.css("#" + for_id).first
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,93 @@
1
+ require "English"
2
+
3
+ require "webrat/core_extensions/blank"
4
+ require "webrat/core/elements/element"
5
+
6
+ module Webrat
7
+ class Link < Element #:nodoc:
8
+
9
+ def self.xpath_search
10
+ [".//a[@href]"]
11
+ end
12
+
13
+ def click(options = {})
14
+ method = options[:method] || http_method
15
+ return if href =~ /^#/ && method == :get
16
+
17
+ options[:javascript] = true if options[:javascript].nil?
18
+
19
+ if options[:javascript]
20
+ @session.request_page(absolute_href, method, data)
21
+ else
22
+ @session.request_page(absolute_href, :get, {})
23
+ end
24
+ end
25
+
26
+ protected
27
+
28
+ def id
29
+ @element["id"]
30
+ end
31
+
32
+ def data
33
+ authenticity_token.blank? ? {} : {"authenticity_token" => authenticity_token}
34
+ end
35
+
36
+ def title
37
+ @element["title"]
38
+ end
39
+
40
+ def href
41
+ @element["href"]
42
+ end
43
+
44
+ def absolute_href
45
+ if href =~ /^\?/
46
+ "#{@session.current_url}#{href}"
47
+ elsif href !~ %r{^https?://} && (href !~ /^\//)
48
+ "#{@session.current_url}/#{href}"
49
+ else
50
+ href
51
+ end
52
+ end
53
+
54
+ def authenticity_token
55
+ return unless onclick && onclick.include?("s.setAttribute('name', 'authenticity_token');") &&
56
+ onclick =~ /s\.setAttribute\('value', '([a-f0-9]{40})'\);/
57
+ $LAST_MATCH_INFO.captures.first
58
+ end
59
+
60
+ def onclick
61
+ @element["onclick"]
62
+ end
63
+
64
+ def http_method
65
+ if !onclick.blank? && onclick.include?("f.submit()")
66
+ http_method_from_js_form
67
+ else
68
+ :get
69
+ end
70
+ end
71
+
72
+ def http_method_from_js_form
73
+ if onclick.include?("m.setAttribute('name', '_method')")
74
+ http_method_from_fake_method_param
75
+ else
76
+ :post
77
+ end
78
+ end
79
+
80
+ def http_method_from_fake_method_param
81
+ if onclick.include?("m.setAttribute('value', 'delete')")
82
+ :delete
83
+ elsif onclick.include?("m.setAttribute('value', 'put')")
84
+ :put
85
+ elsif onclick.include?("m.setAttribute('value', 'post')")
86
+ :post
87
+ else
88
+ raise Webrat::WebratError.new("No HTTP method for _method param in #{onclick.inspect}")
89
+ end
90
+ end
91
+
92
+ end
93
+ end