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,21 @@
1
+ require "webrat/core/matchers/have_selector"
2
+
3
+ module Webrat
4
+ module HaveTagMatcher
5
+
6
+ def have_tag(*args, &block)
7
+ have_selector(*args, &block)
8
+ end
9
+
10
+ alias_method :match_tag, :have_tag
11
+
12
+ def assert_have_tag(*args, &block)
13
+ assert_have_selector(*args, &block)
14
+ end
15
+
16
+ def assert_have_no_tag(*args, &block)
17
+ assert_have_no_selector(*args, &block)
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,122 @@
1
+ require "webrat/core/xml"
2
+
3
+ module Webrat
4
+ module Matchers
5
+
6
+ class HaveXpath #:nodoc:
7
+ def initialize(expected, options = {}, &block)
8
+ @expected = expected
9
+ @options = options
10
+ @block = block
11
+ end
12
+
13
+ def matches?(stringlike, &block)
14
+ @block ||= block
15
+ matched = matches(stringlike)
16
+
17
+ if @options[:count]
18
+ matched.size == @options[:count].to_i && (!@block || @block.call(matched))
19
+ else
20
+ matched.any? && (!@block || @block.call(matched))
21
+ end
22
+ end
23
+
24
+ def matches(stringlike)
25
+ nokogiri_matches(stringlike)
26
+ end
27
+
28
+ def nokogiri_matches(stringlike)
29
+ if Nokogiri::XML::NodeSet === stringlike
30
+ @query = query.gsub(%r'^//', './/')
31
+ else
32
+ @query = query
33
+ end
34
+
35
+ add_options_conditions_to(@query)
36
+
37
+ @document = Webrat::XML.document(stringlike)
38
+ @document.xpath(*@query)
39
+ end
40
+
41
+ def add_options_conditions_to(query)
42
+ add_attributes_conditions_to(query)
43
+ add_content_condition_to(query)
44
+ end
45
+
46
+ def add_attributes_conditions_to(query)
47
+ attribute_conditions = []
48
+
49
+ @options.each do |key, value|
50
+ next if [:content, :count].include?(key)
51
+ attribute_conditions << "@#{key} = #{xpath_escape(value)}"
52
+ end
53
+
54
+ if attribute_conditions.any?
55
+ query << "[#{attribute_conditions.join(' and ')}]"
56
+ end
57
+ end
58
+
59
+ def add_content_condition_to(query)
60
+ if @options[:content]
61
+ query << "[contains(., #{xpath_escape(@options[:content])})]"
62
+ end
63
+ end
64
+
65
+ def query
66
+ @expected
67
+ end
68
+
69
+ # ==== Returns
70
+ # String:: The failure message.
71
+ def failure_message
72
+ "expected following text to match xpath #{@expected}:\n#{@document}"
73
+ end
74
+
75
+ # ==== Returns
76
+ # String:: The failure message to be displayed in negative matches.
77
+ def negative_failure_message
78
+ "expected following text to not match xpath #{@expected}:\n#{@document}"
79
+ end
80
+
81
+ protected
82
+
83
+ def xpath_escape(string)
84
+ if string.include?("'") && string.include?('"')
85
+ parts = string.split("'").map do |part|
86
+ "'#{part}'"
87
+ end
88
+
89
+ "concat(" + parts.join(", \"'\", ") + ")"
90
+ elsif string.include?("'")
91
+ "\"#{string}\""
92
+ else
93
+ "'#{string}'"
94
+ end
95
+ end
96
+
97
+ end
98
+
99
+ # Matches HTML content against an XPath query
100
+ #
101
+ # ==== Parameters
102
+ # expected<String>:: The XPath query to look for.
103
+ #
104
+ # ==== Returns
105
+ # HaveXpath:: A new have xpath matcher.
106
+ def have_xpath(expected, options = {}, &block)
107
+ HaveXpath.new(expected, options, &block)
108
+ end
109
+ alias_method :match_xpath, :have_xpath
110
+
111
+ def assert_have_xpath(expected, options = {}, &block)
112
+ hs = HaveXpath.new(expected, options, &block)
113
+ assert hs.matches?(response_body), hs.failure_message
114
+ end
115
+
116
+ def assert_have_no_xpath(expected, options = {}, &block)
117
+ hs = HaveXpath.new(expected, options, &block)
118
+ assert !hs.matches?(response_body), hs.negative_failure_message
119
+ end
120
+
121
+ end
122
+ end
@@ -0,0 +1,4 @@
1
+ require "webrat/core/matchers/have_xpath"
2
+ require "webrat/core/matchers/have_selector"
3
+ require "webrat/core/matchers/have_tag"
4
+ require "webrat/core/matchers/have_content"
@@ -0,0 +1,64 @@
1
+ module Webrat
2
+ module Methods #:nodoc:
3
+
4
+ def self.delegate_to_session(*meths)
5
+ meths.each do |meth|
6
+ self.class_eval <<-RUBY
7
+ def #{meth}(*args, &blk)
8
+ webrat_session.#{meth}(*args, &blk)
9
+ end
10
+ RUBY
11
+ end
12
+ end
13
+
14
+ def webrat
15
+ webrat_session
16
+ end
17
+
18
+ def webrat_session
19
+ @_webrat_session ||= begin
20
+ session = Webrat.session_class.new
21
+ session.adapter = Webrat.adapter_class.new(self) if session.respond_to?(:adapter=)
22
+ session
23
+ end
24
+ end
25
+
26
+ # all of these methods delegate to the @session, which should
27
+ # be created transparently.
28
+ #
29
+ # Note that when using Webrat, #request also uses @session, so
30
+ # that #request and webrat native functions behave interchangably
31
+
32
+ delegate_to_session \
33
+ :visits, :visit,
34
+ :within,
35
+ :header, :http_accept, :basic_auth,
36
+ :save_and_open_page,
37
+ :fills_in, :fill_in,
38
+ :checks, :check,
39
+ :unchecks, :uncheck,
40
+ :chooses, :choose,
41
+ :selects, :select,
42
+ :unselects, :unselect,
43
+ :attaches_file, :attach_file,
44
+ :current_page,
45
+ :current_url,
46
+ :clicks_link, :click_link,
47
+ :clicks_area, :click_area,
48
+ :clicks_button, :click_button,
49
+ :reload, :reloads,
50
+ :clicks_link_within, :click_link_within,
51
+ :field_labeled,
52
+ :select_option,
53
+ :set_hidden_field, :submit_form,
54
+ :request_page, :current_dom,
55
+ :response_body,
56
+ :selects_date, :selects_time, :selects_datetime,
57
+ :select_date, :select_time, :select_datetime,
58
+ :field_by_xpath,
59
+ :field_with_id,
60
+ :selenium,
61
+ :simulate, :automate,
62
+ :field_named
63
+ end
64
+ end
@@ -0,0 +1,18 @@
1
+ module Webrat #:nodoc:
2
+ module MIME #:nodoc:
3
+ MIME_TYPES = Rack::Mime::MIME_TYPES.dup.merge(
4
+ ".multipart_form" => "multipart/form-data",
5
+ ".url_encoded_form" => "application/x-www-form-urlencoded"
6
+ ).freeze
7
+
8
+ def mime_type(type)
9
+ return type if type.nil? || type.to_s.include?("/")
10
+ type = ".#{type}" unless type.to_s[0] == ?.
11
+ MIME_TYPES.fetch(type) { |type|
12
+ raise ArgumentError.new("Invalid Mime type: #{type}")
13
+ }
14
+ end
15
+
16
+ module_function :mime_type
17
+ end
18
+ end
@@ -0,0 +1,48 @@
1
+ module Webrat
2
+ module SaveAndOpenPage
3
+ # Saves the page out to RAILS_ROOT/tmp/ and opens it in the default
4
+ # web browser if on OS X. Useful for debugging.
5
+ #
6
+ # Example:
7
+ # save_and_open_page
8
+ def save_and_open_page
9
+ return unless File.exist?(saved_page_dir)
10
+
11
+ filename = "#{saved_page_dir}/webrat-#{Time.now.to_i}.html"
12
+
13
+ File.open(filename, "w") do |f|
14
+ f.write rewrite_css_and_image_references(response_body)
15
+ end
16
+
17
+ open_in_browser(filename)
18
+ end
19
+
20
+ def open_in_browser(path) # :nodoc
21
+ require "launchy"
22
+ Launchy::Browser.run(path)
23
+ rescue LoadError
24
+ warn "Sorry, you need to install launchy to open pages: `gem install launchy`"
25
+ end
26
+
27
+ def rewrite_css_and_image_references(response_html) # :nodoc:
28
+ return response_html unless doc_root
29
+ response_html.gsub(/("|')\/(stylesheets|images)/, '\1' + doc_root + '/\2')
30
+ end
31
+
32
+ def saved_page_dir #:nodoc:
33
+ File.expand_path(".")
34
+ end
35
+
36
+ def doc_root #:nodoc:
37
+ nil
38
+ end
39
+
40
+ private
41
+
42
+ # accessor for testing
43
+ def ruby_platform
44
+ RUBY_PLATFORM
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,365 @@
1
+ require "webrat/core/elements/form"
2
+ require "webrat/core/locators"
3
+ require "webrat/core_extensions/deprecate"
4
+
5
+ module Webrat
6
+ # An HTML element (link, button, field, etc.) that Webrat expected was not found on the page
7
+ class NotFoundError < WebratError
8
+ end
9
+
10
+ class Scope
11
+ include Logging
12
+ include Locators
13
+
14
+ def self.from_page(session, response, response_body) #:nodoc:
15
+ new(session) do
16
+ @response = response
17
+ @response_body = response_body
18
+ end
19
+ end
20
+
21
+ def self.from_scope(session, scope, selector) #:nodoc:
22
+ new(session) do
23
+ @scope = scope
24
+ @selector = selector
25
+ end
26
+ end
27
+
28
+ attr_reader :session
29
+
30
+ def initialize(session, &block) #:nodoc:
31
+ @session = session
32
+ instance_eval(&block) if block_given?
33
+
34
+ if @selector && scoped_dom.nil?
35
+ raise Webrat::NotFoundError.new("The scope was not found on the page: #{@selector.inspect}")
36
+ end
37
+ end
38
+
39
+ # Verifies an input field or textarea exists on the current page, and stores a value for
40
+ # it which will be sent when the form is submitted.
41
+ #
42
+ # Examples:
43
+ # fill_in "Email", :with => "user@example.com"
44
+ # fill_in "user[email]", :with => "user@example.com"
45
+ #
46
+ # The field value is required, and must be specified in <tt>options[:with]</tt>.
47
+ # <tt>field</tt> can be either the value of a name attribute (i.e. <tt>user[email]</tt>)
48
+ # or the text inside a <tt><label></tt> element that points at the <tt><input></tt> field.
49
+ def fill_in(field_locator, options = {})
50
+ field = locate_field(field_locator, TextField, TextareaField, PasswordField)
51
+ field.raise_error_if_disabled
52
+ field.set(options[:with])
53
+ end
54
+
55
+ webrat_deprecate :fills_in, :fill_in
56
+
57
+ # Verifies that a hidden field exists on the current page and sets
58
+ # the value to that given by the <tt>:to</tt> option.
59
+ #
60
+ # Example:
61
+ # set_hidden_field 'user_id', :to => 1
62
+ def set_hidden_field(field_locator, options = {})
63
+ field = locate_field(field_locator, HiddenField)
64
+ field.set(options[:to])
65
+ end
66
+
67
+ # Verifies that an input checkbox exists on the current page and marks it
68
+ # as checked, so that the value will be submitted with the form.
69
+ #
70
+ # Example:
71
+ # check 'Remember Me'
72
+ def check(field_locator)
73
+ locate_field(field_locator, CheckboxField).check
74
+ end
75
+
76
+ webrat_deprecate :checks, :check
77
+
78
+ # Verifies that an input checkbox exists on the current page and marks it
79
+ # as unchecked, so that the value will not be submitted with the form.
80
+ #
81
+ # Example:
82
+ # uncheck 'Remember Me'
83
+ def uncheck(field_locator)
84
+ locate_field(field_locator, CheckboxField).uncheck
85
+ end
86
+
87
+ webrat_deprecate :unchecks, :uncheck
88
+
89
+ # Verifies that an input radio button exists on the current page and marks it
90
+ # as checked, so that the value will be submitted with the form.
91
+ #
92
+ # Example:
93
+ # choose 'First Option'
94
+ def choose(field_locator)
95
+ locate_field(field_locator, RadioField).choose
96
+ end
97
+
98
+ webrat_deprecate :chooses, :choose
99
+
100
+ # Verifies that a an option element exists on the current page with the specified
101
+ # text. You can optionally restrict the search to a specific select list by
102
+ # assigning <tt>options[:from]</tt> the value of the select list's name or
103
+ # a label. Stores the option's value to be sent when the form is submitted.
104
+ #
105
+ # Examples:
106
+ # select "January"
107
+ # select "February", :from => "event_month"
108
+ # select "February", :from => "Event Month"
109
+ def select(option_text, options = {})
110
+ select_option(option_text, options[:from]).choose
111
+ end
112
+
113
+ webrat_deprecate :selects, :select
114
+
115
+ # Verifies that a an option element exists on the current page with the specified
116
+ # text. You can optionally restrict the search to a specific select list by
117
+ # assigning <tt>options[:from]</tt> the value of the select list's name or
118
+ # a label. Remove the option's value before the form is submitted.
119
+ #
120
+ # Examples:
121
+ # unselect "January"
122
+ # unselect "February", :from => "event_month"
123
+ # unselect "February", :from => "Event Month"
124
+ def unselect(option_text, options={})
125
+ select_option(option_text, options[:from]).unchoose
126
+ end
127
+
128
+ webrat_deprecate :unselects, :unselect
129
+
130
+ DATE_TIME_SUFFIXES = {
131
+ :year => '1i',
132
+ :month => '2i',
133
+ :day => '3i',
134
+ :hour => '4i',
135
+ :minute => '5i'
136
+ }
137
+
138
+ # Verifies that date elements (year, month, day) exist on the current page
139
+ # with the specified values. You can optionally restrict the search to a specific
140
+ # date's elements by assigning <tt>options[:from]</tt> the value of the date's
141
+ # label. Selects all the date elements with date provided. The date provided may
142
+ # be a string or a Date/Time object.
143
+ #
144
+ # Rail's convention is used for detecting the date elements. All elements
145
+ # are assumed to have a shared prefix. You may also specify the prefix
146
+ # by assigning <tt>options[:id_prefix]</tt>.
147
+ #
148
+ # Examples:
149
+ # select_date "January 23, 2004"
150
+ # select_date "April 26, 1982", :from => "Birthday"
151
+ # select_date Date.parse("December 25, 2000"), :from => "Event"
152
+ # select_date "April 26, 1982", :id_prefix => 'birthday'
153
+ def select_date(date_to_select, options ={})
154
+ date = date_to_select.is_a?(Date) || date_to_select.is_a?(Time) ?
155
+ date_to_select : Date.parse(date_to_select)
156
+
157
+ id_prefix = locate_id_prefix(options) do
158
+ year_field = FieldByIdLocator.new(@session, dom, /(.*?)_#{DATE_TIME_SUFFIXES[:year]}$/).locate
159
+ raise NotFoundError.new("No date fields were found") unless year_field && year_field.id =~ /(.*?)_1i/
160
+ $1
161
+ end
162
+
163
+ select date.year, :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:year]}"
164
+ select date.strftime('%B'), :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:month]}"
165
+ select date.day, :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:day]}"
166
+ end
167
+
168
+ webrat_deprecate :selects_date, :select_date
169
+
170
+ # Verifies that time elements (hour, minute) exist on the current page
171
+ # with the specified values. You can optionally restrict the search to a specific
172
+ # time's elements by assigning <tt>options[:from]</tt> the value of the time's
173
+ # label. Selects all the time elements with date provided. The time provided may
174
+ # be a string or a Time object.
175
+ #
176
+ # Rail's convention is used for detecting the time elements. All elements are
177
+ # assumed to have a shared prefix. You may specify the prefix by assigning
178
+ # <tt>options[:id_prefix]</tt>.
179
+ #
180
+ # Note: Just like Rails' time_select helper this assumes the form is using
181
+ # 24 hour select boxes, and not 12 hours with AM/PM.
182
+ #
183
+ # Examples:
184
+ # select_time "9:30"
185
+ # select_date "3:30PM", :from => "Party Time"
186
+ # select_date Time.parse("10:00PM"), :from => "Event"
187
+ # select_date "10:30AM", :id_prefix => 'meeting'
188
+ def select_time(time_to_select, options ={})
189
+ time = time_to_select.is_a?(Time) ? time_to_select : Time.parse(time_to_select)
190
+
191
+ id_prefix = locate_id_prefix(options) do
192
+ hour_field = FieldByIdLocator.new(@session, dom, /(.*?)_#{DATE_TIME_SUFFIXES[:hour]}$/).locate
193
+ raise NotFoundError.new("No time fields were found") unless hour_field && hour_field.id =~ /(.*?)_4i/
194
+ $1
195
+ end
196
+
197
+ select time.hour.to_s.rjust(2,'0'), :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:hour]}"
198
+ select time.min.to_s.rjust(2,'0'), :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:minute]}"
199
+ end
200
+
201
+ webrat_deprecate :selects_time, :select_time
202
+
203
+ # Verifies and selects all the date and time elements on the current page.
204
+ # See #select_time and #select_date for more details and available options.
205
+ #
206
+ # Examples:
207
+ # select_datetime "January 23, 2004 10:30AM"
208
+ # select_datetime "April 26, 1982 7:00PM", :from => "Birthday"
209
+ # select_datetime Time.parse("December 25, 2000 15:30"), :from => "Event"
210
+ # select_datetime "April 26, 1982 5:50PM", :id_prefix => 'birthday'
211
+ def select_datetime(time_to_select, options ={})
212
+ time = time_to_select.is_a?(Time) ? time_to_select : Time.parse(time_to_select)
213
+
214
+ options[:id_prefix] ||= (options[:from] ? FieldByIdLocator.new(@session, dom, options[:from]).locate : nil)
215
+
216
+ select_date time, options
217
+ select_time time, options
218
+ end
219
+
220
+ webrat_deprecate :selects_datetime, :select_datetime
221
+
222
+ # Verifies that an input file field exists on the current page and sets
223
+ # its value to the given +file+, so that the file will be uploaded
224
+ # along with the form. An optional <tt>content_type</tt> may be given.
225
+ #
226
+ # Example:
227
+ # attach_file "Resume", "/path/to/the/resume.txt"
228
+ # attach_file "Photo", "/path/to/the/image.png", "image/png"
229
+ def attach_file(field_locator, path, content_type = nil)
230
+ locate_field(field_locator, FileField).set(path, content_type)
231
+ end
232
+
233
+ webrat_deprecate :attaches_file, :attach_file
234
+
235
+ # Issues a request for the URL pointed to by an <tt>area</tt> tag
236
+ # on the current page, follows any redirects, and verifies the
237
+ # final page load was successful.
238
+ #
239
+ # The area used is the first area whose title or id contains the
240
+ # given +area_name+ (case is ignored).
241
+ #
242
+ # Example:
243
+ # click_area 'Australia'
244
+ def click_area(area_name)
245
+ find_area(area_name).click
246
+ end
247
+
248
+ webrat_deprecate :clicks_area, :click_area
249
+
250
+ # Issues a request for the URL pointed to by a link on the current page,
251
+ # follows any redirects, and verifies the final page load was successful.
252
+ #
253
+ # click_link has very basic support for detecting Rails-generated
254
+ # JavaScript onclick handlers for PUT, POST and DELETE links, as well as
255
+ # CSRF authenticity tokens if they are present.
256
+ #
257
+ # Javascript imitation can be disabled by passing the option :javascript => false
258
+ #
259
+ # Passing a :method in the options hash overrides the HTTP method used
260
+ # for making the link request
261
+ #
262
+ # It will try to find links by (in order of precedence):
263
+ # innerHTML, with simple &nbsp; handling
264
+ # title
265
+ # id
266
+ #
267
+ # innerHTML and title are matchable by text subtring or Regexp
268
+ # id is matchable by full text equality or Regexp
269
+ #
270
+ # Example:
271
+ # click_link "Sign up"
272
+ # click_link "Sign up", :javascript => false
273
+ # click_link "Sign up", :method => :put
274
+ def click_link(text_or_title_or_id, options = {})
275
+ find_link(text_or_title_or_id).click(options)
276
+ end
277
+
278
+ webrat_deprecate :clicks_link, :click_link
279
+
280
+ # Verifies that a submit button exists for the form, then submits the form, follows
281
+ # any redirects, and verifies the final page was successful.
282
+ #
283
+ # Example:
284
+ # click_button "Login"
285
+ # click_button
286
+ #
287
+ # The URL and HTTP method for the form submission are automatically read from the
288
+ # <tt>action</tt> and <tt>method</tt> attributes of the <tt><form></tt> element.
289
+ def click_button(value = nil)
290
+ find_button(value).click
291
+ end
292
+
293
+ webrat_deprecate :clicks_button, :click_button
294
+
295
+ # Submit the form with the given id.
296
+ #
297
+ # Note that +click_button+ is usually preferrable for simulating
298
+ # form submissions, as you may specify part of the button text
299
+ # rather than the form id.
300
+ #
301
+ # Example:
302
+ # submit_form 'login'
303
+ def submit_form(id)
304
+ FormLocator.new(@session, dom, id).locate.submit
305
+ end
306
+
307
+ def dom # :nodoc:
308
+ return @dom if @dom
309
+
310
+ if @selector
311
+ @dom = scoped_dom
312
+ else
313
+ @dom = page_dom
314
+ end
315
+
316
+ return @dom
317
+ end
318
+
319
+ protected
320
+
321
+ def page_dom #:nodoc:
322
+ return @response.dom if @response.respond_to?(:dom)
323
+
324
+ if @session.xml_content_type?
325
+ dom = Webrat::XML.xml_document(@response_body)
326
+ else
327
+ dom = Webrat::XML.html_document(@response_body)
328
+ end
329
+
330
+ Webrat::XML.define_dom_method(@response, dom)
331
+ return dom
332
+ end
333
+
334
+ def scoped_dom
335
+ @scope.dom.css(@selector).first
336
+ end
337
+
338
+ def locate_field(field_locator, *field_types) #:nodoc:
339
+ if field_locator.is_a?(Field)
340
+ field_locator
341
+ else
342
+ field(field_locator, *field_types)
343
+ end
344
+ end
345
+
346
+ def locate_id_prefix(options, &location_strategy) #:nodoc:
347
+ return options[:id_prefix] if options[:id_prefix]
348
+
349
+ if options[:from]
350
+ if (label = LabelLocator.new(@session, dom, options[:from]).locate)
351
+ label.for_id
352
+ else
353
+ raise NotFoundError.new("Could not find the label with text #{options[:from]}")
354
+ end
355
+ else
356
+ yield
357
+ end
358
+ end
359
+
360
+ def forms #:nodoc:
361
+ @forms ||= Form.load_all(@session, dom)
362
+ end
363
+
364
+ end
365
+ end