indirect-webrat 0.7.4

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 (218) hide show
  1. data/.document +4 -0
  2. data/.gitignore +21 -0
  3. data/Gemfile +14 -0
  4. data/History.txt +470 -0
  5. data/MIT-LICENSE.txt +19 -0
  6. data/README.rdoc +85 -0
  7. data/Rakefile +143 -0
  8. data/Thorfile +118 -0
  9. data/install.rb +1 -0
  10. data/lib/webrat.rb +18 -0
  11. data/lib/webrat/adapters/mechanize.rb +94 -0
  12. data/lib/webrat/adapters/merb.rb +11 -0
  13. data/lib/webrat/adapters/rack.rb +30 -0
  14. data/lib/webrat/adapters/rails.rb +77 -0
  15. data/lib/webrat/adapters/sinatra.rb +9 -0
  16. data/lib/webrat/core.rb +13 -0
  17. data/lib/webrat/core/configuration.rb +114 -0
  18. data/lib/webrat/core/elements/area.rb +31 -0
  19. data/lib/webrat/core/elements/element.rb +33 -0
  20. data/lib/webrat/core/elements/field.rb +438 -0
  21. data/lib/webrat/core/elements/form.rb +127 -0
  22. data/lib/webrat/core/elements/label.rb +31 -0
  23. data/lib/webrat/core/elements/link.rb +93 -0
  24. data/lib/webrat/core/elements/select_option.rb +48 -0
  25. data/lib/webrat/core/locators.rb +20 -0
  26. data/lib/webrat/core/locators/area_locator.rb +38 -0
  27. data/lib/webrat/core/locators/button_locator.rb +54 -0
  28. data/lib/webrat/core/locators/field_by_id_locator.rb +37 -0
  29. data/lib/webrat/core/locators/field_labeled_locator.rb +56 -0
  30. data/lib/webrat/core/locators/field_locator.rb +25 -0
  31. data/lib/webrat/core/locators/field_named_locator.rb +41 -0
  32. data/lib/webrat/core/locators/form_locator.rb +19 -0
  33. data/lib/webrat/core/locators/label_locator.rb +34 -0
  34. data/lib/webrat/core/locators/link_locator.rb +82 -0
  35. data/lib/webrat/core/locators/locator.rb +20 -0
  36. data/lib/webrat/core/locators/select_option_locator.rb +59 -0
  37. data/lib/webrat/core/logging.rb +23 -0
  38. data/lib/webrat/core/matchers.rb +4 -0
  39. data/lib/webrat/core/matchers/have_content.rb +68 -0
  40. data/lib/webrat/core/matchers/have_selector.rb +85 -0
  41. data/lib/webrat/core/matchers/have_tag.rb +21 -0
  42. data/lib/webrat/core/matchers/have_xpath.rb +124 -0
  43. data/lib/webrat/core/methods.rb +73 -0
  44. data/lib/webrat/core/mime.rb +18 -0
  45. data/lib/webrat/core/save_and_open_page.rb +28 -0
  46. data/lib/webrat/core/scope.rb +362 -0
  47. data/lib/webrat/core/session.rb +318 -0
  48. data/lib/webrat/core/xml.rb +44 -0
  49. data/lib/webrat/core_extensions/blank.rb +58 -0
  50. data/lib/webrat/core_extensions/deprecate.rb +8 -0
  51. data/lib/webrat/core_extensions/detect_mapped.rb +12 -0
  52. data/lib/webrat/core_extensions/meta_class.rb +6 -0
  53. data/lib/webrat/core_extensions/nil_to_query_string.rb +5 -0
  54. data/lib/webrat/core_extensions/tcp_socket.rb +27 -0
  55. data/lib/webrat/integrations/merb.rb +10 -0
  56. data/lib/webrat/integrations/rack.rb +9 -0
  57. data/lib/webrat/integrations/rails.rb +25 -0
  58. data/lib/webrat/integrations/rspec-rails.rb +11 -0
  59. data/lib/webrat/integrations/selenium.rb +11 -0
  60. data/lib/webrat/merb.rb +9 -0
  61. data/lib/webrat/rspec-rails.rb +2 -0
  62. data/lib/webrat/selenium.rb +70 -0
  63. data/lib/webrat/selenium/application_server_factory.rb +43 -0
  64. data/lib/webrat/selenium/application_servers.rb +5 -0
  65. data/lib/webrat/selenium/application_servers/base.rb +46 -0
  66. data/lib/webrat/selenium/application_servers/external.rb +26 -0
  67. data/lib/webrat/selenium/application_servers/merb.rb +50 -0
  68. data/lib/webrat/selenium/application_servers/rack.rb +51 -0
  69. data/lib/webrat/selenium/application_servers/rails.rb +44 -0
  70. data/lib/webrat/selenium/application_servers/sinatra.rb +37 -0
  71. data/lib/webrat/selenium/location_strategy_javascript/button.js +19 -0
  72. data/lib/webrat/selenium/location_strategy_javascript/label.js +48 -0
  73. data/lib/webrat/selenium/location_strategy_javascript/webrat.js +6 -0
  74. data/lib/webrat/selenium/location_strategy_javascript/webratlink.js +32 -0
  75. data/lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js +15 -0
  76. data/lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js +5 -0
  77. data/lib/webrat/selenium/matchers.rb +4 -0
  78. data/lib/webrat/selenium/matchers/have_content.rb +78 -0
  79. data/lib/webrat/selenium/matchers/have_selector.rb +57 -0
  80. data/lib/webrat/selenium/matchers/have_tag.rb +72 -0
  81. data/lib/webrat/selenium/matchers/have_xpath.rb +53 -0
  82. data/lib/webrat/selenium/selenium_extensions.js +6 -0
  83. data/lib/webrat/selenium/selenium_rc_server.rb +89 -0
  84. data/lib/webrat/selenium/selenium_session.rb +276 -0
  85. data/lib/webrat/selenium/silence_stream.rb +18 -0
  86. data/spec/fakes/test_adapter.rb +33 -0
  87. data/spec/integration/mechanize/Rakefile +7 -0
  88. data/spec/integration/mechanize/config.ru +2 -0
  89. data/spec/integration/mechanize/sample_app.rb +35 -0
  90. data/spec/integration/mechanize/spec/mechanize_spec.rb +30 -0
  91. data/spec/integration/mechanize/spec/spec_helper.rb +29 -0
  92. data/spec/integration/merb/.gitignore +21 -0
  93. data/spec/integration/merb/Rakefile +35 -0
  94. data/spec/integration/merb/app/controllers/application.rb +2 -0
  95. data/spec/integration/merb/app/controllers/exceptions.rb +13 -0
  96. data/spec/integration/merb/app/controllers/testing.rb +27 -0
  97. data/spec/integration/merb/app/views/exceptions/not_acceptable.html.erb +63 -0
  98. data/spec/integration/merb/app/views/exceptions/not_found.html.erb +47 -0
  99. data/spec/integration/merb/app/views/layout/application.html.erb +12 -0
  100. data/spec/integration/merb/app/views/testing/show_form.html.erb +27 -0
  101. data/spec/integration/merb/app/views/testing/upload.html.erb +9 -0
  102. data/spec/integration/merb/config/environments/development.rb +15 -0
  103. data/spec/integration/merb/config/environments/rake.rb +11 -0
  104. data/spec/integration/merb/config/environments/test.rb +14 -0
  105. data/spec/integration/merb/config/init.rb +25 -0
  106. data/spec/integration/merb/config/rack.rb +11 -0
  107. data/spec/integration/merb/config/router.rb +34 -0
  108. data/spec/integration/merb/spec/spec.opts +1 -0
  109. data/spec/integration/merb/spec/spec_helper.rb +26 -0
  110. data/spec/integration/merb/spec/webrat_spec.rb +39 -0
  111. data/spec/integration/merb/tasks/merb.thor/app_script.rb +31 -0
  112. data/spec/integration/merb/tasks/merb.thor/common.rb +64 -0
  113. data/spec/integration/merb/tasks/merb.thor/gem_ext.rb +124 -0
  114. data/spec/integration/merb/tasks/merb.thor/main.thor +150 -0
  115. data/spec/integration/merb/tasks/merb.thor/ops.rb +93 -0
  116. data/spec/integration/merb/tasks/merb.thor/utils.rb +40 -0
  117. data/spec/integration/rack/Rakefile +5 -0
  118. data/spec/integration/rack/app.rb +89 -0
  119. data/spec/integration/rack/test/helper.rb +20 -0
  120. data/spec/integration/rack/test/webrat_rack_test.rb +74 -0
  121. data/spec/integration/rails/.gitignore +3 -0
  122. data/spec/integration/rails/Rakefile +30 -0
  123. data/spec/integration/rails/app/controllers/application_controller.rb +15 -0
  124. data/spec/integration/rails/app/controllers/buttons_controller.rb +7 -0
  125. data/spec/integration/rails/app/controllers/fields_controller.rb +4 -0
  126. data/spec/integration/rails/app/controllers/links_controller.rb +7 -0
  127. data/spec/integration/rails/app/controllers/webrat_controller.rb +46 -0
  128. data/spec/integration/rails/app/helpers/buttons_helper.rb +2 -0
  129. data/spec/integration/rails/app/helpers/fields_helper.rb +2 -0
  130. data/spec/integration/rails/app/helpers/links_helper.rb +2 -0
  131. data/spec/integration/rails/app/views/buttons/show.html.erb +9 -0
  132. data/spec/integration/rails/app/views/fields/show.html.erb +9 -0
  133. data/spec/integration/rails/app/views/links/show.html.erb +5 -0
  134. data/spec/integration/rails/app/views/webrat/before_redirect_form.html.erb +4 -0
  135. data/spec/integration/rails/app/views/webrat/buttons.html.erb +9 -0
  136. data/spec/integration/rails/app/views/webrat/form.html.erb +28 -0
  137. data/spec/integration/rails/app/views/webrat/within.html.erb +3 -0
  138. data/spec/integration/rails/config/boot.rb +109 -0
  139. data/spec/integration/rails/config/environment.rb +12 -0
  140. data/spec/integration/rails/config/environments/development.rb +17 -0
  141. data/spec/integration/rails/config/environments/selenium.rb +22 -0
  142. data/spec/integration/rails/config/environments/test.rb +22 -0
  143. data/spec/integration/rails/config/initializers/inflections.rb +10 -0
  144. data/spec/integration/rails/config/initializers/mime_types.rb +5 -0
  145. data/spec/integration/rails/config/initializers/new_rails_defaults.rb +17 -0
  146. data/spec/integration/rails/config/locales/en.yml +5 -0
  147. data/spec/integration/rails/config/routes.rb +19 -0
  148. data/spec/integration/rails/public/404.html +30 -0
  149. data/spec/integration/rails/public/422.html +30 -0
  150. data/spec/integration/rails/public/500.html +33 -0
  151. data/spec/integration/rails/script/about +4 -0
  152. data/spec/integration/rails/script/console +3 -0
  153. data/spec/integration/rails/script/dbconsole +3 -0
  154. data/spec/integration/rails/script/destroy +3 -0
  155. data/spec/integration/rails/script/generate +3 -0
  156. data/spec/integration/rails/script/performance/benchmarker +3 -0
  157. data/spec/integration/rails/script/performance/profiler +3 -0
  158. data/spec/integration/rails/script/performance/request +3 -0
  159. data/spec/integration/rails/script/plugin +3 -0
  160. data/spec/integration/rails/script/process/inspector +3 -0
  161. data/spec/integration/rails/script/process/reaper +3 -0
  162. data/spec/integration/rails/script/process/spawner +3 -0
  163. data/spec/integration/rails/script/runner +3 -0
  164. data/spec/integration/rails/script/server +3 -0
  165. data/spec/integration/rails/test/integration/button_click_test.rb +66 -0
  166. data/spec/integration/rails/test/integration/fill_in_test.rb +24 -0
  167. data/spec/integration/rails/test/integration/link_click_test.rb +27 -0
  168. data/spec/integration/rails/test/integration/webrat_test.rb +123 -0
  169. data/spec/integration/rails/test/test_helper.rb +27 -0
  170. data/spec/integration/sinatra/Rakefile +5 -0
  171. data/spec/integration/sinatra/classic_app.rb +63 -0
  172. data/spec/integration/sinatra/modular_app.rb +15 -0
  173. data/spec/integration/sinatra/test/classic_app_test.rb +38 -0
  174. data/spec/integration/sinatra/test/modular_app_test.rb +18 -0
  175. data/spec/integration/sinatra/test/test_helper.rb +16 -0
  176. data/spec/private/core/configuration_spec.rb +87 -0
  177. data/spec/private/core/field_spec.rb +83 -0
  178. data/spec/private/core/form_spec.rb +51 -0
  179. data/spec/private/core/link_spec.rb +24 -0
  180. data/spec/private/core/session_spec.rb +182 -0
  181. data/spec/private/mechanize/mechanize_adapter_spec.rb +96 -0
  182. data/spec/private/nokogiri_spec.rb +77 -0
  183. data/spec/private/rails/attaches_file_spec.rb +114 -0
  184. data/spec/private/rails/rails_adapter_spec.rb +79 -0
  185. data/spec/private/selenium/application_servers/rails_spec.rb +26 -0
  186. data/spec/public/basic_auth_spec.rb +35 -0
  187. data/spec/public/check_spec.rb +191 -0
  188. data/spec/public/choose_spec.rb +118 -0
  189. data/spec/public/click_area_spec.rb +106 -0
  190. data/spec/public/click_button_spec.rb +494 -0
  191. data/spec/public/click_link_spec.rb +544 -0
  192. data/spec/public/fill_in_spec.rb +224 -0
  193. data/spec/public/locators/field_by_xpath_spec.rb +19 -0
  194. data/spec/public/locators/field_labeled_spec.rb +172 -0
  195. data/spec/public/locators/field_with_id_spec.rb +16 -0
  196. data/spec/public/matchers/contain_spec.rb +118 -0
  197. data/spec/public/matchers/have_selector_spec.rb +146 -0
  198. data/spec/public/matchers/have_tag_spec.rb +39 -0
  199. data/spec/public/matchers/have_xpath_spec.rb +165 -0
  200. data/spec/public/reload_spec.rb +10 -0
  201. data/spec/public/save_and_open_spec.rb +49 -0
  202. data/spec/public/select_date_spec.rb +112 -0
  203. data/spec/public/select_datetime_spec.rb +137 -0
  204. data/spec/public/select_spec.rb +474 -0
  205. data/spec/public/select_time_spec.rb +100 -0
  206. data/spec/public/selenium/application_server_factory_spec.rb +49 -0
  207. data/spec/public/selenium/application_servers/external_spec.rb +12 -0
  208. data/spec/public/selenium/selenium_session_spec.rb +37 -0
  209. data/spec/public/set_hidden_field_spec.rb +5 -0
  210. data/spec/public/submit_form_spec.rb +56 -0
  211. data/spec/public/visit_spec.rb +58 -0
  212. data/spec/public/within_spec.rb +177 -0
  213. data/spec/rcov.opts +1 -0
  214. data/spec/spec.opts +2 -0
  215. data/spec/spec_helper.rb +53 -0
  216. data/vendor/selenium-server.jar +0 -0
  217. data/webrat.gemspec +355 -0
  218. metadata +424 -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,124 @@
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
+ @block.call(matched) if @block
18
+
19
+ if @options[:count]
20
+ matched.size == @options[:count].to_i
21
+ else
22
+ matched.any?
23
+ end
24
+ end
25
+
26
+ def matches(stringlike)
27
+ nokogiri_matches(stringlike)
28
+ end
29
+
30
+ def nokogiri_matches(stringlike)
31
+ if Nokogiri::XML::NodeSet === stringlike
32
+ @query = query.gsub(%r'^//', './/')
33
+ else
34
+ @query = query
35
+ end
36
+
37
+ add_options_conditions_to(@query)
38
+
39
+ @document = Webrat::XML.document(stringlike)
40
+ @document.xpath(*@query)
41
+ end
42
+
43
+ def add_options_conditions_to(query)
44
+ add_attributes_conditions_to(query)
45
+ add_content_condition_to(query)
46
+ end
47
+
48
+ def add_attributes_conditions_to(query)
49
+ attribute_conditions = []
50
+
51
+ @options.each do |key, value|
52
+ next if [:content, :count].include?(key)
53
+ attribute_conditions << "@#{key} = #{xpath_escape(value)}"
54
+ end
55
+
56
+ if attribute_conditions.any?
57
+ query << "[#{attribute_conditions.join(' and ')}]"
58
+ end
59
+ end
60
+
61
+ def add_content_condition_to(query)
62
+ if @options[:content]
63
+ query << "[contains(., #{xpath_escape(@options[:content])})]"
64
+ end
65
+ end
66
+
67
+ def query
68
+ @expected
69
+ end
70
+
71
+ # ==== Returns
72
+ # String:: The failure message.
73
+ def failure_message
74
+ "expected following text to match xpath #{@expected}:\n#{@document}"
75
+ end
76
+
77
+ # ==== Returns
78
+ # String:: The failure message to be displayed in negative matches.
79
+ def negative_failure_message
80
+ "expected following text to not match xpath #{@expected}:\n#{@document}"
81
+ end
82
+
83
+ protected
84
+
85
+ def xpath_escape(string)
86
+ if string.include?("'") && string.include?('"')
87
+ parts = string.split("'").map do |part|
88
+ "'#{part}'"
89
+ end
90
+
91
+ "concat(" + parts.join(", \"'\", ") + ")"
92
+ elsif string.include?("'")
93
+ "\"#{string}\""
94
+ else
95
+ "'#{string}'"
96
+ end
97
+ end
98
+
99
+ end
100
+
101
+ # Matches HTML content against an XPath query
102
+ #
103
+ # ==== Parameters
104
+ # expected<String>:: The XPath query to look for.
105
+ #
106
+ # ==== Returns
107
+ # HaveXpath:: A new have xpath matcher.
108
+ def have_xpath(expected, options = {}, &block)
109
+ HaveXpath.new(expected, options, &block)
110
+ end
111
+ alias_method :match_xpath, :have_xpath
112
+
113
+ def assert_have_xpath(expected, options = {}, &block)
114
+ hs = HaveXpath.new(expected, options, &block)
115
+ assert hs.matches?(response_body), hs.failure_message
116
+ end
117
+
118
+ def assert_have_no_xpath(expected, options = {}, &block)
119
+ hs = HaveXpath.new(expected, options, &block)
120
+ assert !hs.matches?(response_body), hs.negative_failure_message
121
+ end
122
+
123
+ end
124
+ end
@@ -0,0 +1,73 @@
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, __FILE__, __LINE__)
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
+ # Temporary hack to work with Rails 3
27
+ def response
28
+ if Webrat.configuration.mode == :rack
29
+ webrat_session.response
30
+ else
31
+ super
32
+ end
33
+ end
34
+
35
+ # all of these methods delegate to the @session, which should
36
+ # be created transparently.
37
+ #
38
+ # Note that when using Webrat, #request also uses @session, so
39
+ # that #request and webrat native functions behave interchangably
40
+
41
+ delegate_to_session \
42
+ :visits, :visit,
43
+ :within,
44
+ :header, :http_accept, :basic_auth,
45
+ :save_and_open_page,
46
+ :fills_in, :fill_in,
47
+ :checks, :check,
48
+ :unchecks, :uncheck,
49
+ :chooses, :choose,
50
+ :selects, :select,
51
+ :unselects, :unselect,
52
+ :attaches_file, :attach_file,
53
+ :current_page,
54
+ :current_url,
55
+ :clicks_link, :click_link,
56
+ :clicks_area, :click_area,
57
+ :clicks_button, :click_button,
58
+ :reload, :reloads,
59
+ :clicks_link_within, :click_link_within,
60
+ :field_labeled,
61
+ :select_option,
62
+ :set_hidden_field, :submit_form,
63
+ :request_page, :current_dom,
64
+ :response_body,
65
+ :selects_date, :selects_time, :selects_datetime,
66
+ :select_date, :select_time, :select_datetime,
67
+ :field_by_xpath,
68
+ :field_with_id,
69
+ :selenium,
70
+ :simulate, :automate,
71
+ :field_named, :follow_redirect!
72
+ end
73
+ 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) { |invalid_type|
12
+ raise ArgumentError.new("Invalid Mime type: #{invalid_type}")
13
+ }
14
+ end
15
+
16
+ module_function :mime_type
17
+ end
18
+ end
@@ -0,0 +1,28 @@
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?(Webrat.configuration.saved_pages_dir)
10
+
11
+ filename = "#{Webrat.configuration.saved_pages_dir}/webrat-#{Time.now.to_i}.html"
12
+
13
+ File.open(filename, "w") do |f|
14
+ f.write 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.open(path)
23
+ rescue LoadError
24
+ warn "Sorry, you need to install launchy to open pages: `gem install launchy`"
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,362 @@
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
+ @selector, @dom = nil
32
+ @session = session
33
+ instance_eval(&block) if block_given?
34
+
35
+ if @selector && scoped_dom.nil?
36
+ raise Webrat::NotFoundError.new("The scope was not found on the page: #{@selector.inspect}")
37
+ end
38
+ end
39
+
40
+ # Verifies an input field or textarea exists on the current page, and stores a value for
41
+ # it which will be sent when the form is submitted.
42
+ #
43
+ # Examples:
44
+ # fill_in "Email", :with => "user@example.com"
45
+ # fill_in "user[email]", :with => "user@example.com"
46
+ #
47
+ # The field value is required, and must be specified in <tt>options[:with]</tt>.
48
+ # <tt>field</tt> can be either the value of a name attribute (i.e. <tt>user[email]</tt>)
49
+ # or the text inside a <tt><label></tt> element that points at the <tt><input></tt> field.
50
+ def fill_in(field_locator, options = {})
51
+ field = locate_field(field_locator, TextField, TextareaField, PasswordField)
52
+ field.raise_error_if_disabled
53
+ field.set(options[:with])
54
+ end
55
+
56
+ webrat_deprecate :fills_in, :fill_in
57
+
58
+ # Verifies that a hidden field exists on the current page and sets
59
+ # the value to that given by the <tt>:to</tt> option.
60
+ #
61
+ # Example:
62
+ # set_hidden_field 'user_id', :to => 1
63
+ def set_hidden_field(field_locator, options = {})
64
+ field = locate_field(field_locator, HiddenField)
65
+ field.set(options[:to])
66
+ end
67
+
68
+ # Verifies that an input checkbox exists on the current page and marks it
69
+ # as checked, so that the value will be submitted with the form.
70
+ #
71
+ # Example:
72
+ # check 'Remember Me'
73
+ def check(field_locator)
74
+ locate_field(field_locator, CheckboxField).check
75
+ end
76
+
77
+ webrat_deprecate :checks, :check
78
+
79
+ # Verifies that an input checkbox exists on the current page and marks it
80
+ # as unchecked, so that the value will not be submitted with the form.
81
+ #
82
+ # Example:
83
+ # uncheck 'Remember Me'
84
+ def uncheck(field_locator)
85
+ locate_field(field_locator, CheckboxField).uncheck
86
+ end
87
+
88
+ webrat_deprecate :unchecks, :uncheck
89
+
90
+ # Verifies that an input radio button exists on the current page and marks it
91
+ # as checked, so that the value will be submitted with the form.
92
+ #
93
+ # Example:
94
+ # choose 'First Option'
95
+ def choose(field_locator)
96
+ locate_field(field_locator, RadioField).choose
97
+ end
98
+
99
+ webrat_deprecate :chooses, :choose
100
+
101
+ # Verifies that a an option element exists on the current page with the specified
102
+ # text. You can optionally restrict the search to a specific select list by
103
+ # assigning <tt>options[:from]</tt> the value of the select list's name or
104
+ # a label. Stores the option's value to be sent when the form is submitted.
105
+ #
106
+ # Examples:
107
+ # select "January"
108
+ # select "February", :from => "event_month"
109
+ # select "February", :from => "Event Month"
110
+ def select(option_text, options = {})
111
+ select_option(option_text, options[:from]).choose
112
+ end
113
+
114
+ webrat_deprecate :selects, :select
115
+
116
+ # Verifies that a an option element exists on the current page with the specified
117
+ # text. You can optionally restrict the search to a specific select list by
118
+ # assigning <tt>options[:from]</tt> the value of the select list's name or
119
+ # a label. Remove the option's value before the form is submitted.
120
+ #
121
+ # Examples:
122
+ # unselect "January"
123
+ # unselect "February", :from => "event_month"
124
+ # unselect "February", :from => "Event Month"
125
+ def unselect(option_text, options={})
126
+ select_option(option_text, options[:from]).unchoose
127
+ end
128
+
129
+ webrat_deprecate :unselects, :unselect
130
+
131
+ DATE_TIME_SUFFIXES = {
132
+ :year => '1i',
133
+ :month => '2i',
134
+ :day => '3i',
135
+ :hour => '4i',
136
+ :minute => '5i'
137
+ }
138
+
139
+ # Verifies that date elements (year, month, day) exist on the current page
140
+ # with the specified values. You can optionally restrict the search to a specific
141
+ # date's elements by assigning <tt>options[:from]</tt> the value of the date's
142
+ # label. Selects all the date elements with date provided. The date provided may
143
+ # be a string or a Date/Time object.
144
+ #
145
+ # Rail's convention is used for detecting the date elements. All elements
146
+ # are assumed to have a shared prefix. You may also specify the prefix
147
+ # by assigning <tt>options[:id_prefix]</tt>.
148
+ #
149
+ # Examples:
150
+ # select_date "January 23, 2004"
151
+ # select_date "April 26, 1982", :from => "Birthday"
152
+ # select_date Date.parse("December 25, 2000"), :from => "Event"
153
+ # select_date "April 26, 1982", :id_prefix => 'birthday'
154
+ def select_date(date_to_select, options ={})
155
+ date = date_to_select.is_a?(Date) || date_to_select.is_a?(Time) ?
156
+ date_to_select : Date.parse(date_to_select)
157
+
158
+ id_prefix = locate_id_prefix(options) do
159
+ year_field = FieldByIdLocator.new(@session, dom, /(.*?)_#{DATE_TIME_SUFFIXES[:year]}$/).locate
160
+ raise NotFoundError.new("No date fields were found") unless year_field && year_field.id =~ /(.*?)_1i/
161
+ $1
162
+ end
163
+
164
+ select date.year, :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:year]}"
165
+ select date.strftime('%B'), :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:month]}"
166
+ select date.day, :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:day]}"
167
+ end
168
+
169
+ webrat_deprecate :selects_date, :select_date
170
+
171
+ # Verifies that time elements (hour, minute) exist on the current page
172
+ # with the specified values. You can optionally restrict the search to a specific
173
+ # time's elements by assigning <tt>options[:from]</tt> the value of the time's
174
+ # label. Selects all the time elements with date provided. The time provided may
175
+ # be a string or a Time object.
176
+ #
177
+ # Rail's convention is used for detecting the time elements. All elements are
178
+ # assumed to have a shared prefix. You may specify the prefix by assigning
179
+ # <tt>options[:id_prefix]</tt>.
180
+ #
181
+ # Note: Just like Rails' time_select helper this assumes the form is using
182
+ # 24 hour select boxes, and not 12 hours with AM/PM.
183
+ #
184
+ # Examples:
185
+ # select_time "9:30"
186
+ # select_date "3:30PM", :from => "Party Time"
187
+ # select_date Time.parse("10:00PM"), :from => "Event"
188
+ # select_date "10:30AM", :id_prefix => 'meeting'
189
+ def select_time(time_to_select, options ={})
190
+ time = time_to_select.is_a?(Time) ? time_to_select : Time.parse(time_to_select)
191
+
192
+ id_prefix = locate_id_prefix(options) do
193
+ hour_field = FieldByIdLocator.new(@session, dom, /(.*?)_#{DATE_TIME_SUFFIXES[:hour]}$/).locate
194
+ raise NotFoundError.new("No time fields were found") unless hour_field && hour_field.id =~ /(.*?)_4i/
195
+ $1
196
+ end
197
+
198
+ select time.hour.to_s.rjust(2,'0'), :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:hour]}"
199
+ select time.min.to_s.rjust(2,'0'), :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:minute]}"
200
+ end
201
+
202
+ webrat_deprecate :selects_time, :select_time
203
+
204
+ # Verifies and selects all the date and time elements on the current page.
205
+ # See #select_time and #select_date for more details and available options.
206
+ #
207
+ # Examples:
208
+ # select_datetime "January 23, 2004 10:30AM"
209
+ # select_datetime "April 26, 1982 7:00PM", :from => "Birthday"
210
+ # select_datetime Time.parse("December 25, 2000 15:30"), :from => "Event"
211
+ # select_datetime "April 26, 1982 5:50PM", :id_prefix => 'birthday'
212
+ def select_datetime(time_to_select, options ={})
213
+ time = time_to_select.is_a?(Time) ? time_to_select : Time.parse(time_to_select)
214
+
215
+ options[:id_prefix] ||= (options[:from] ? FieldByIdLocator.new(@session, dom, options[:from]).locate : nil)
216
+
217
+ select_date time, options
218
+ select_time time, options
219
+ end
220
+
221
+ webrat_deprecate :selects_datetime, :select_datetime
222
+
223
+ # Verifies that an input file field exists on the current page and sets
224
+ # its value to the given +file+, so that the file will be uploaded
225
+ # along with the form. An optional <tt>content_type</tt> may be given.
226
+ #
227
+ # Example:
228
+ # attach_file "Resume", "/path/to/the/resume.txt"
229
+ # attach_file "Photo", "/path/to/the/image.png", "image/png"
230
+ def attach_file(field_locator, path, content_type = nil)
231
+ locate_field(field_locator, FileField).set(path, content_type)
232
+ end
233
+
234
+ webrat_deprecate :attaches_file, :attach_file
235
+
236
+ # Issues a request for the URL pointed to by an <tt>area</tt> tag
237
+ # on the current page, follows any redirects, and verifies the
238
+ # final page load was successful.
239
+ #
240
+ # The area used is the first area whose title or id contains the
241
+ # given +area_name+ (case is ignored).
242
+ #
243
+ # Example:
244
+ # click_area 'Australia'
245
+ def click_area(area_name)
246
+ find_area(area_name).click
247
+ end
248
+
249
+ webrat_deprecate :clicks_area, :click_area
250
+
251
+ # Issues a request for the URL pointed to by a link on the current page,
252
+ # follows any redirects, and verifies the final page load was successful.
253
+ #
254
+ # click_link has very basic support for detecting Rails-generated
255
+ # JavaScript onclick handlers for PUT, POST and DELETE links, as well as
256
+ # CSRF authenticity tokens if they are present.
257
+ #
258
+ # Javascript imitation can be disabled by passing the option :javascript => false
259
+ #
260
+ # Passing a :method in the options hash overrides the HTTP method used
261
+ # for making the link request
262
+ #
263
+ # It will try to find links by (in order of precedence):
264
+ # innerHTML, with simple &nbsp; handling
265
+ # title
266
+ # id
267
+ #
268
+ # innerHTML and title are matchable by text subtring or Regexp
269
+ # id is matchable by full text equality or Regexp
270
+ #
271
+ # Example:
272
+ # click_link "Sign up"
273
+ # click_link "Sign up", :javascript => false
274
+ # click_link "Sign up", :method => :put
275
+ def click_link(text_or_title_or_id, options = {})
276
+ find_link(text_or_title_or_id).click(options)
277
+ end
278
+
279
+ webrat_deprecate :clicks_link, :click_link
280
+
281
+ # Verifies that a submit button exists for the form, then submits the form, follows
282
+ # any redirects, and verifies the final page was successful.
283
+ #
284
+ # Example:
285
+ # click_button "Login"
286
+ # click_button
287
+ #
288
+ # The URL and HTTP method for the form submission are automatically read from the
289
+ # <tt>action</tt> and <tt>method</tt> attributes of the <tt><form></tt> element.
290
+ def click_button(value = nil)
291
+ find_button(value).click
292
+ end
293
+
294
+ webrat_deprecate :clicks_button, :click_button
295
+
296
+ # Submit the form with the given id.
297
+ #
298
+ # Note that +click_button+ is usually preferrable for simulating
299
+ # form submissions, as you may specify part of the button text
300
+ # rather than the form id.
301
+ #
302
+ # Example:
303
+ # submit_form 'login'
304
+ def submit_form(id)
305
+ FormLocator.new(@session, dom, id).locate.submit
306
+ end
307
+
308
+ def dom # :nodoc:
309
+ return @dom if @dom
310
+
311
+ if @selector
312
+ @dom = scoped_dom
313
+ else
314
+ @dom = page_dom
315
+ end
316
+
317
+ return @dom
318
+ end
319
+
320
+ protected
321
+
322
+ def page_dom #:nodoc:
323
+ return @response.dom if @response.respond_to?(:dom)
324
+
325
+ dom = Webrat::XML.document(@response_body)
326
+
327
+ Webrat::XML.define_dom_method(@response, dom)
328
+ return dom
329
+ end
330
+
331
+ def scoped_dom
332
+ @scope.dom.css(@selector).first
333
+ end
334
+
335
+ def locate_field(field_locator, *field_types) #:nodoc:
336
+ if field_locator.is_a?(Field)
337
+ field_locator
338
+ else
339
+ field(field_locator, *field_types)
340
+ end
341
+ end
342
+
343
+ def locate_id_prefix(options, &location_strategy) #:nodoc:
344
+ return options[:id_prefix] if options[:id_prefix]
345
+
346
+ if options[:from]
347
+ if (label = LabelLocator.new(@session, dom, options[:from]).locate)
348
+ label.for_id
349
+ else
350
+ raise NotFoundError.new("Could not find the label with text #{options[:from]}")
351
+ end
352
+ else
353
+ yield
354
+ end
355
+ end
356
+
357
+ def forms #:nodoc:
358
+ @forms ||= Form.load_all(@session, dom)
359
+ end
360
+
361
+ end
362
+ end