kbaum-webrat 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (214) hide show
  1. data/.document +4 -0
  2. data/.gitignore +15 -0
  3. data/History.txt +406 -0
  4. data/MIT-LICENSE.txt +19 -0
  5. data/README.rdoc +85 -0
  6. data/Rakefile +186 -0
  7. data/VERSION +1 -0
  8. data/install.rb +1 -0
  9. data/lib/webrat.rb +18 -0
  10. data/lib/webrat/adapters/mechanize.rb +78 -0
  11. data/lib/webrat/adapters/merb.rb +11 -0
  12. data/lib/webrat/adapters/rack.rb +25 -0
  13. data/lib/webrat/adapters/rails.rb +96 -0
  14. data/lib/webrat/adapters/sinatra.rb +9 -0
  15. data/lib/webrat/core.rb +13 -0
  16. data/lib/webrat/core/configuration.rb +96 -0
  17. data/lib/webrat/core/elements/area.rb +31 -0
  18. data/lib/webrat/core/elements/element.rb +33 -0
  19. data/lib/webrat/core/elements/field.rb +487 -0
  20. data/lib/webrat/core/elements/form.rb +103 -0
  21. data/lib/webrat/core/elements/label.rb +31 -0
  22. data/lib/webrat/core/elements/link.rb +93 -0
  23. data/lib/webrat/core/elements/select_option.rb +48 -0
  24. data/lib/webrat/core/locators.rb +20 -0
  25. data/lib/webrat/core/locators/area_locator.rb +38 -0
  26. data/lib/webrat/core/locators/button_locator.rb +54 -0
  27. data/lib/webrat/core/locators/field_by_id_locator.rb +37 -0
  28. data/lib/webrat/core/locators/field_labeled_locator.rb +56 -0
  29. data/lib/webrat/core/locators/field_locator.rb +25 -0
  30. data/lib/webrat/core/locators/field_named_locator.rb +41 -0
  31. data/lib/webrat/core/locators/form_locator.rb +19 -0
  32. data/lib/webrat/core/locators/label_locator.rb +34 -0
  33. data/lib/webrat/core/locators/link_locator.rb +74 -0
  34. data/lib/webrat/core/locators/locator.rb +20 -0
  35. data/lib/webrat/core/locators/select_option_locator.rb +59 -0
  36. data/lib/webrat/core/logging.rb +23 -0
  37. data/lib/webrat/core/matchers.rb +4 -0
  38. data/lib/webrat/core/matchers/have_content.rb +68 -0
  39. data/lib/webrat/core/matchers/have_selector.rb +74 -0
  40. data/lib/webrat/core/matchers/have_tag.rb +21 -0
  41. data/lib/webrat/core/matchers/have_xpath.rb +122 -0
  42. data/lib/webrat/core/methods.rb +64 -0
  43. data/lib/webrat/core/mime.rb +18 -0
  44. data/lib/webrat/core/save_and_open_page.rb +48 -0
  45. data/lib/webrat/core/scope.rb +365 -0
  46. data/lib/webrat/core/session.rb +307 -0
  47. data/lib/webrat/core/xml.rb +72 -0
  48. data/lib/webrat/core_extensions/blank.rb +58 -0
  49. data/lib/webrat/core_extensions/deprecate.rb +8 -0
  50. data/lib/webrat/core_extensions/detect_mapped.rb +12 -0
  51. data/lib/webrat/core_extensions/meta_class.rb +6 -0
  52. data/lib/webrat/core_extensions/nil_to_param.rb +5 -0
  53. data/lib/webrat/core_extensions/tcp_socket.rb +27 -0
  54. data/lib/webrat/integrations/merb.rb +10 -0
  55. data/lib/webrat/integrations/rails.rb +9 -0
  56. data/lib/webrat/integrations/rspec-rails.rb +10 -0
  57. data/lib/webrat/integrations/selenium.rb +11 -0
  58. data/lib/webrat/merb.rb +9 -0
  59. data/lib/webrat/rspec-rails.rb +2 -0
  60. data/lib/webrat/selenium.rb +70 -0
  61. data/lib/webrat/selenium/application_server_factory.rb +40 -0
  62. data/lib/webrat/selenium/application_servers.rb +5 -0
  63. data/lib/webrat/selenium/application_servers/base.rb +46 -0
  64. data/lib/webrat/selenium/application_servers/external.rb +26 -0
  65. data/lib/webrat/selenium/application_servers/merb.rb +50 -0
  66. data/lib/webrat/selenium/application_servers/rails.rb +44 -0
  67. data/lib/webrat/selenium/application_servers/sinatra.rb +37 -0
  68. data/lib/webrat/selenium/location_strategy_javascript/button.js +19 -0
  69. data/lib/webrat/selenium/location_strategy_javascript/label.js +24 -0
  70. data/lib/webrat/selenium/location_strategy_javascript/webrat.js +5 -0
  71. data/lib/webrat/selenium/location_strategy_javascript/webratlink.js +12 -0
  72. data/lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js +15 -0
  73. data/lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js +5 -0
  74. data/lib/webrat/selenium/matchers.rb +4 -0
  75. data/lib/webrat/selenium/matchers/have_content.rb +66 -0
  76. data/lib/webrat/selenium/matchers/have_selector.rb +74 -0
  77. data/lib/webrat/selenium/matchers/have_tag.rb +49 -0
  78. data/lib/webrat/selenium/matchers/have_xpath.rb +45 -0
  79. data/lib/webrat/selenium/selenium_extensions.js +6 -0
  80. data/lib/webrat/selenium/selenium_rc_server.rb +86 -0
  81. data/lib/webrat/selenium/selenium_session.rb +250 -0
  82. data/lib/webrat/selenium/silence_stream.rb +18 -0
  83. data/selenium_rc_server.patch +20 -0
  84. data/spec/fakes/test_adapter.rb +37 -0
  85. data/spec/integration/mechanize/Rakefile +7 -0
  86. data/spec/integration/mechanize/config.ru +2 -0
  87. data/spec/integration/mechanize/sample_app.rb +20 -0
  88. data/spec/integration/mechanize/spec/mechanize_spec.rb +22 -0
  89. data/spec/integration/mechanize/spec/spec_helper.rb +27 -0
  90. data/spec/integration/merb/.gitignore +21 -0
  91. data/spec/integration/merb/Rakefile +35 -0
  92. data/spec/integration/merb/app/controllers/application.rb +2 -0
  93. data/spec/integration/merb/app/controllers/exceptions.rb +13 -0
  94. data/spec/integration/merb/app/controllers/testing.rb +27 -0
  95. data/spec/integration/merb/app/views/exceptions/not_acceptable.html.erb +63 -0
  96. data/spec/integration/merb/app/views/exceptions/not_found.html.erb +47 -0
  97. data/spec/integration/merb/app/views/layout/application.html.erb +12 -0
  98. data/spec/integration/merb/app/views/testing/show_form.html.erb +27 -0
  99. data/spec/integration/merb/app/views/testing/upload.html.erb +9 -0
  100. data/spec/integration/merb/config/environments/development.rb +15 -0
  101. data/spec/integration/merb/config/environments/rake.rb +11 -0
  102. data/spec/integration/merb/config/environments/test.rb +14 -0
  103. data/spec/integration/merb/config/init.rb +25 -0
  104. data/spec/integration/merb/config/rack.rb +11 -0
  105. data/spec/integration/merb/config/router.rb +34 -0
  106. data/spec/integration/merb/spec/spec.opts +1 -0
  107. data/spec/integration/merb/spec/spec_helper.rb +26 -0
  108. data/spec/integration/merb/spec/webrat_spec.rb +39 -0
  109. data/spec/integration/merb/tasks/merb.thor/app_script.rb +31 -0
  110. data/spec/integration/merb/tasks/merb.thor/common.rb +64 -0
  111. data/spec/integration/merb/tasks/merb.thor/gem_ext.rb +124 -0
  112. data/spec/integration/merb/tasks/merb.thor/main.thor +150 -0
  113. data/spec/integration/merb/tasks/merb.thor/ops.rb +93 -0
  114. data/spec/integration/merb/tasks/merb.thor/utils.rb +40 -0
  115. data/spec/integration/rack/Rakefile +5 -0
  116. data/spec/integration/rack/app.rb +89 -0
  117. data/spec/integration/rack/test/helper.rb +21 -0
  118. data/spec/integration/rack/test/webrat_rack_test.rb +73 -0
  119. data/spec/integration/rails/.gitignore +3 -0
  120. data/spec/integration/rails/Rakefile +30 -0
  121. data/spec/integration/rails/app/controllers/application.rb +15 -0
  122. data/spec/integration/rails/app/controllers/buttons_controller.rb +7 -0
  123. data/spec/integration/rails/app/controllers/fields_controller.rb +4 -0
  124. data/spec/integration/rails/app/controllers/links_controller.rb +7 -0
  125. data/spec/integration/rails/app/controllers/webrat_controller.rb +43 -0
  126. data/spec/integration/rails/app/helpers/buttons_helper.rb +2 -0
  127. data/spec/integration/rails/app/helpers/fields_helper.rb +2 -0
  128. data/spec/integration/rails/app/helpers/links_helper.rb +2 -0
  129. data/spec/integration/rails/app/views/buttons/show.html.erb +11 -0
  130. data/spec/integration/rails/app/views/fields/show.html.erb +9 -0
  131. data/spec/integration/rails/app/views/links/show.html.erb +5 -0
  132. data/spec/integration/rails/app/views/webrat/before_redirect_form.html.erb +4 -0
  133. data/spec/integration/rails/app/views/webrat/buttons.html.erb +11 -0
  134. data/spec/integration/rails/app/views/webrat/form.html.erb +28 -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 +18 -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 +97 -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 +110 -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. data/webrat.gemspec +356 -0
  214. metadata +410 -0
@@ -0,0 +1,96 @@
1
+ require "webrat/core_extensions/deprecate"
2
+
3
+ module Webrat
4
+
5
+ # Configures Webrat. If this is not done, Webrat will be created
6
+ # with all of the default settings.
7
+ def self.configure(configuration = Webrat.configuration)
8
+ yield configuration if block_given?
9
+ @@configuration = configuration
10
+ end
11
+
12
+ def self.configuration # :nodoc:
13
+ @@configuration ||= Webrat::Configuration.new
14
+ end
15
+
16
+ # Webrat can be configured using the Webrat.configure method. For example:
17
+ #
18
+ # Webrat.configure do |config|
19
+ # config.mode = :sinatra
20
+ # end
21
+ class Configuration
22
+
23
+ # Webrat's mode, set automatically when requiring webrat/rails, webrat/merb, etc.
24
+ attr_reader :mode # :nodoc:
25
+
26
+ # Save and open pages with error status codes (500-599) in a browser? Defualts to true.
27
+ attr_writer :open_error_files
28
+
29
+ # Which rails environment should the selenium tests be run in? Defaults to selenium.
30
+ attr_accessor :application_environment
31
+ webrat_deprecate :selenium_environment, :application_environment
32
+ webrat_deprecate :selenium_environment=, :application_environment=
33
+
34
+ # Which port is the application running on for selenium testing? Defaults to 3001.
35
+ attr_accessor :application_port
36
+ webrat_deprecate :selenium_port, :application_port
37
+ webrat_deprecate :selenium_port=, :application_port=
38
+
39
+ # Which underlying app framework we're testing with selenium
40
+ attr_accessor :application_framework
41
+
42
+ # Which server the application is running on for selenium testing? Defaults to localhost
43
+ attr_accessor :application_address
44
+
45
+ # Which server Selenium server is running on. Defaults to nil(server starts in webrat process and runs locally)
46
+ attr_accessor :selenium_server_address
47
+
48
+ # Which server Selenium port is running on. Defaults to 4444
49
+ attr_accessor :selenium_server_port
50
+
51
+ # Set the key that Selenium uses to determine the browser running. Default *firefox
52
+ attr_accessor :selenium_browser_key
53
+
54
+ # Set the timeout for waiting for the browser process to start
55
+ attr_accessor :selenium_browser_startup_timeout
56
+
57
+ # Set the selenium wait general response wait time
58
+ attr_accessor :selenium_response_wait_time
59
+
60
+ # How many redirects to the same URL should be halted as an infinite redirect
61
+ # loop? Defaults to 10
62
+ attr_accessor :infinite_redirect_limit
63
+
64
+ def initialize # :nodoc:
65
+ self.open_error_files = true
66
+ self.application_environment = :test
67
+ self.application_port = 3001
68
+ self.application_address = 'localhost'
69
+ self.application_framework = :rails
70
+ self.selenium_server_port = 4444
71
+ self.infinite_redirect_limit = 10
72
+ self.selenium_browser_key = '*firefox'
73
+ self.selenium_browser_startup_timeout = 5
74
+ self.selenium_response_wait_time = 5
75
+ end
76
+
77
+ def open_error_files? #:nodoc:
78
+ @open_error_files ? true : false
79
+ end
80
+
81
+ # Allows setting of webrat's mode, valid modes are:
82
+ # :rails, :selenium, :rack, :sinatra, :mechanize, :merb
83
+ def mode=(mode)
84
+ @mode = mode.to_sym
85
+
86
+ begin
87
+ require("webrat/integrations/#{mode}")
88
+ rescue LoadError
89
+ # Only some modes have integration code that needs to
90
+ # be loaded, so this is OK
91
+ end
92
+ end
93
+
94
+ end
95
+
96
+ end
@@ -0,0 +1,31 @@
1
+ require "webrat/core/elements/element"
2
+
3
+ module Webrat
4
+ class Area < Element #:nodoc:
5
+
6
+ def self.xpath_search
7
+ [".//area"]
8
+ end
9
+
10
+ def click(method = nil, options = {})
11
+ @session.request_page(absolute_href, :get, {})
12
+ end
13
+
14
+ protected
15
+
16
+ def href
17
+ @element["href"]
18
+ end
19
+
20
+ def absolute_href
21
+ if href =~ /^\?/
22
+ "#{@session.current_url}#{href}"
23
+ elsif href !~ %r{^https?://[\w|.]+(/.*)} && (href !~ /^\//)
24
+ "#{@session.current_url}/#{href}"
25
+ else
26
+ href
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,33 @@
1
+ module Webrat
2
+
3
+ class Element # :nodoc:
4
+
5
+ def self.load_all(session, dom)
6
+ dom.xpath(*xpath_search).map do |element|
7
+ load(session, element)
8
+ end
9
+ end
10
+
11
+ def self.load(session, element)
12
+ return nil if element.nil?
13
+ session.elements[element.path] ||= self.new(session, element)
14
+ end
15
+
16
+ attr_reader :element
17
+
18
+ def initialize(session, element)
19
+ @session = session
20
+ @element = element
21
+ end
22
+
23
+ def path
24
+ @element.path
25
+ end
26
+
27
+ def inspect
28
+ "#<#{self.class} @element=#{element.inspect}>"
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -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