honkster-webrat 0.4.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. data/History.txt +358 -0
  2. data/MIT-LICENSE.txt +19 -0
  3. data/README.rdoc +85 -0
  4. data/Rakefile +200 -0
  5. data/install.rb +1 -0
  6. data/lib/webrat.rb +31 -0
  7. data/lib/webrat/core.rb +14 -0
  8. data/lib/webrat/core/configuration.rb +102 -0
  9. data/lib/webrat/core/elements/area.rb +31 -0
  10. data/lib/webrat/core/elements/element.rb +33 -0
  11. data/lib/webrat/core/elements/field.rb +411 -0
  12. data/lib/webrat/core/elements/form.rb +103 -0
  13. data/lib/webrat/core/elements/label.rb +31 -0
  14. data/lib/webrat/core/elements/link.rb +93 -0
  15. data/lib/webrat/core/elements/select_option.rb +35 -0
  16. data/lib/webrat/core/locators.rb +20 -0
  17. data/lib/webrat/core/locators/area_locator.rb +38 -0
  18. data/lib/webrat/core/locators/button_locator.rb +54 -0
  19. data/lib/webrat/core/locators/field_by_id_locator.rb +37 -0
  20. data/lib/webrat/core/locators/field_labeled_locator.rb +56 -0
  21. data/lib/webrat/core/locators/field_locator.rb +25 -0
  22. data/lib/webrat/core/locators/field_named_locator.rb +41 -0
  23. data/lib/webrat/core/locators/form_locator.rb +19 -0
  24. data/lib/webrat/core/locators/label_locator.rb +34 -0
  25. data/lib/webrat/core/locators/link_locator.rb +74 -0
  26. data/lib/webrat/core/locators/locator.rb +20 -0
  27. data/lib/webrat/core/locators/select_option_locator.rb +59 -0
  28. data/lib/webrat/core/logging.rb +24 -0
  29. data/lib/webrat/core/matchers.rb +4 -0
  30. data/lib/webrat/core/matchers/have_content.rb +73 -0
  31. data/lib/webrat/core/matchers/have_selector.rb +74 -0
  32. data/lib/webrat/core/matchers/have_tag.rb +21 -0
  33. data/lib/webrat/core/matchers/have_xpath.rb +147 -0
  34. data/lib/webrat/core/methods.rb +63 -0
  35. data/lib/webrat/core/mime.rb +29 -0
  36. data/lib/webrat/core/save_and_open_page.rb +48 -0
  37. data/lib/webrat/core/scope.rb +350 -0
  38. data/lib/webrat/core/session.rb +291 -0
  39. data/lib/webrat/core/xml.rb +115 -0
  40. data/lib/webrat/core/xml/hpricot.rb +19 -0
  41. data/lib/webrat/core/xml/nokogiri.rb +76 -0
  42. data/lib/webrat/core/xml/rexml.rb +24 -0
  43. data/lib/webrat/core_extensions/blank.rb +58 -0
  44. data/lib/webrat/core_extensions/deprecate.rb +8 -0
  45. data/lib/webrat/core_extensions/detect_mapped.rb +12 -0
  46. data/lib/webrat/core_extensions/meta_class.rb +6 -0
  47. data/lib/webrat/core_extensions/nil_to_param.rb +5 -0
  48. data/lib/webrat/core_extensions/tcp_socket.rb +27 -0
  49. data/lib/webrat/mechanize.rb +74 -0
  50. data/lib/webrat/merb.rb +9 -0
  51. data/lib/webrat/merb_multipart_support.rb +27 -0
  52. data/lib/webrat/merb_session.rb +80 -0
  53. data/lib/webrat/rack.rb +24 -0
  54. data/lib/webrat/rack_test.rb +32 -0
  55. data/lib/webrat/rails.rb +105 -0
  56. data/lib/webrat/rspec-rails.rb +10 -0
  57. data/lib/webrat/selenium.rb +81 -0
  58. data/lib/webrat/selenium/application_server_factory.rb +40 -0
  59. data/lib/webrat/selenium/application_servers.rb +5 -0
  60. data/lib/webrat/selenium/application_servers/base.rb +46 -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 +44 -0
  64. data/lib/webrat/selenium/application_servers/sinatra.rb +37 -0
  65. data/lib/webrat/selenium/location_strategy_javascript/button.js +19 -0
  66. data/lib/webrat/selenium/location_strategy_javascript/label.js +24 -0
  67. data/lib/webrat/selenium/location_strategy_javascript/webrat.js +5 -0
  68. data/lib/webrat/selenium/location_strategy_javascript/webratlink.js +12 -0
  69. data/lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js +15 -0
  70. data/lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js +5 -0
  71. data/lib/webrat/selenium/matchers.rb +4 -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/selenium_extensions.js +6 -0
  77. data/lib/webrat/selenium/selenium_rc_server.rb +84 -0
  78. data/lib/webrat/selenium/selenium_session.rb +252 -0
  79. data/lib/webrat/selenium/silence_stream.rb +18 -0
  80. data/lib/webrat/sinatra.rb +44 -0
  81. data/vendor/selenium-server.jar +0 -0
  82. metadata +145 -0
@@ -0,0 +1,4 @@
1
+ require "webrat/selenium/matchers/have_xpath"
2
+ require "webrat/selenium/matchers/have_selector"
3
+ # require "webrat/selenium/matchers/have_tag"
4
+ require "webrat/selenium/matchers/have_content"
@@ -0,0 +1,66 @@
1
+ module Webrat
2
+ module Selenium
3
+ module Matchers
4
+ class HasContent #:nodoc:
5
+ def initialize(content)
6
+ @content = content
7
+ end
8
+
9
+ def matches?(response)
10
+ if @content.is_a?(Regexp)
11
+ text_finder = "regexp:#{@content.source}"
12
+ else
13
+ text_finder = @content
14
+ end
15
+
16
+ response.session.wait_for do
17
+ response.selenium.is_text_present(text_finder)
18
+ end
19
+ rescue Webrat::TimeoutError
20
+ false
21
+ end
22
+
23
+ # ==== Returns
24
+ # String:: The failure message.
25
+ def failure_message
26
+ "expected the following element's content to #{content_message}:\n#{@element}"
27
+ end
28
+
29
+ # ==== Returns
30
+ # String:: The failure message to be displayed in negative matches.
31
+ def negative_failure_message
32
+ "expected the following element's content to not #{content_message}:\n#{@element}"
33
+ end
34
+
35
+ def content_message
36
+ case @content
37
+ when String
38
+ "include \"#{@content}\""
39
+ when Regexp
40
+ "match #{@content.inspect}"
41
+ end
42
+ end
43
+ end
44
+
45
+ # Matches the contents of an HTML document with
46
+ # whatever string is supplied
47
+ def contain(content)
48
+ HasContent.new(content)
49
+ end
50
+
51
+ # Asserts that the body of the response contain
52
+ # the supplied string or regexp
53
+ def assert_contain(content)
54
+ hc = HasContent.new(content)
55
+ assert hc.matches?(response), hc.failure_message
56
+ end
57
+
58
+ # Asserts that the body of the response
59
+ # does not contain the supplied string or regepx
60
+ def assert_not_contain(content)
61
+ hc = HasContent.new(content)
62
+ assert !hc.matches?(response), hc.negative_failure_message
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,49 @@
1
+ module Webrat
2
+ module Selenium
3
+ module Matchers
4
+ class HaveSelector
5
+ def initialize(expected)
6
+ @expected = expected
7
+ end
8
+
9
+ def matches?(response)
10
+ response.session.wait_for do
11
+ response.selenium.is_element_present("css=#{@expected}")
12
+ end
13
+ rescue Webrat::TimeoutError
14
+ false
15
+ end
16
+
17
+ # ==== Returns
18
+ # String:: The failure message.
19
+ def failure_message
20
+ "expected following text to match selector #{@expected}:\n#{@document}"
21
+ end
22
+
23
+ # ==== Returns
24
+ # String:: The failure message to be displayed in negative matches.
25
+ def negative_failure_message
26
+ "expected following text to not match selector #{@expected}:\n#{@document}"
27
+ end
28
+ end
29
+
30
+ def have_selector(content)
31
+ HaveSelector.new(content)
32
+ end
33
+
34
+ # Asserts that the body of the response contains
35
+ # the supplied selector
36
+ def assert_have_selector(expected)
37
+ hs = HaveSelector.new(expected)
38
+ assert hs.matches?(response), hs.failure_message
39
+ end
40
+
41
+ # Asserts that the body of the response
42
+ # does not contain the supplied string or regepx
43
+ def assert_have_no_selector(expected)
44
+ hs = HaveSelector.new(expected)
45
+ assert !hs.matches?(response), hs.negative_failure_message
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,72 @@
1
+ module Webrat
2
+ module Selenium
3
+ module Matchers
4
+
5
+ class HaveTag < HaveSelector #:nodoc:
6
+ # ==== Returns
7
+ # String:: The failure message.
8
+ def failure_message
9
+ "expected following output to contain a #{tag_inspect} tag:\n#{@document}"
10
+ end
11
+
12
+ # ==== Returns
13
+ # String:: The failure message to be displayed in negative matches.
14
+ def negative_failure_message
15
+ "expected following output to omit a #{tag_inspect}:\n#{@document}"
16
+ end
17
+
18
+ def tag_inspect
19
+ options = @expected.last.dup
20
+ content = options.delete(:content)
21
+
22
+ html = "<#{@expected.first}"
23
+ options.each do |k,v|
24
+ html << " #{k}='#{v}'"
25
+ end
26
+
27
+ if content
28
+ html << ">#{content}</#{@expected.first}>"
29
+ else
30
+ html << "/>"
31
+ end
32
+
33
+ html
34
+ end
35
+
36
+ def query
37
+ options = @expected.last.dup
38
+ selector = @expected.first.to_s
39
+
40
+ selector << ":contains('#{options.delete(:content)}')" if options[:content]
41
+
42
+ options.each do |key, value|
43
+ selector << "[#{key}='#{value}']"
44
+ end
45
+
46
+ Nokogiri::CSS.parse(selector).map { |ast| ast.to_xpath }
47
+ end
48
+ end
49
+
50
+ def have_tag(name, attributes = {}, &block)
51
+ HaveTag.new([name, attributes], &block)
52
+ end
53
+
54
+ alias_method :match_tag, :have_tag
55
+
56
+ # Asserts that the body of the response contains
57
+ # the supplied tag with the associated selectors
58
+ def assert_have_tag(name, attributes = {})
59
+ ht = HaveTag.new([name, attributes])
60
+ assert ht.matches?(response), ht.failure_message
61
+ end
62
+
63
+ # Asserts that the body of the response
64
+ # does not contain the supplied string or regepx
65
+ def assert_have_no_tag(name, attributes = {})
66
+ ht = HaveTag.new([name, attributes])
67
+ assert !ht.matches?(response), ht.negative_failure_message
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,45 @@
1
+ module Webrat
2
+ module Selenium
3
+ module Matchers
4
+ class HaveXpath
5
+ def initialize(expected)
6
+ @expected = expected
7
+ end
8
+
9
+ def matches?(response)
10
+ response.session.wait_for do
11
+ response.selenium.is_element_present("xpath=#{@expected}")
12
+ end
13
+ rescue Webrat::TimeoutError
14
+ false
15
+ end
16
+
17
+ # ==== Returns
18
+ # String:: The failure message.
19
+ def failure_message
20
+ "expected following text to match xpath #{@expected}:\n#{@document}"
21
+ end
22
+
23
+ # ==== Returns
24
+ # String:: The failure message to be displayed in negative matches.
25
+ def negative_failure_message
26
+ "expected following text to not match xpath #{@expected}:\n#{@document}"
27
+ end
28
+ end
29
+
30
+ def have_xpath(xpath)
31
+ HaveXpath.new(xpath)
32
+ end
33
+
34
+ def assert_have_xpath(expected)
35
+ hs = HaveXpath.new(expected)
36
+ assert hs.matches?(response), hs.failure_message
37
+ end
38
+
39
+ def assert_have_no_xpath(expected)
40
+ hs = HaveXpath.new(expected)
41
+ assert !hs.matches?(response), hs.negative_failure_message
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,6 @@
1
+ PatternMatcher.strategies['evalregex'] = function(regexpString) {
2
+ this.regexp = eval(regexpString);
3
+ this.matches = function(actual) {
4
+ return this.regexp.test(actual);
5
+ };
6
+ };
@@ -0,0 +1,84 @@
1
+ module Webrat
2
+ module Selenium
3
+
4
+ class SeleniumRCServer
5
+
6
+ include Webrat::Selenium::SilenceStream
7
+
8
+ def self.boot
9
+ new.boot
10
+ end
11
+
12
+ def boot
13
+ return if selenium_grid?
14
+
15
+ start
16
+ wait
17
+ stop_at_exit
18
+ end
19
+
20
+ def start
21
+ silence_stream(STDOUT) do
22
+ remote_control.start :background => true
23
+ end
24
+ end
25
+
26
+ def stop_at_exit
27
+ at_exit do
28
+ stop
29
+ end
30
+ end
31
+
32
+ def remote_control
33
+ return @remote_control if @remote_control
34
+
35
+ @remote_control = ::Selenium::RemoteControl::RemoteControl.new("0.0.0.0",
36
+ Webrat.configuration.selenium_server_port,
37
+ Webrat.configuration.selenium_browser_startup_timeout)
38
+ @remote_control.jar_file = jar_path
39
+
40
+ return @remote_control
41
+ end
42
+
43
+ def jar_path
44
+ File.expand_path(__FILE__ + "../../../../../vendor/selenium-server.jar")
45
+ end
46
+
47
+ def selenium_grid?
48
+ Webrat.configuration.selenium_server_address
49
+ end
50
+
51
+ def wait
52
+ $stderr.print "==> Waiting for Selenium RC server on port #{Webrat.configuration.selenium_server_port}... "
53
+ wait_for_socket
54
+ $stderr.print "Ready!\n"
55
+ rescue SocketError
56
+ fail
57
+ end
58
+
59
+ def wait_for_socket
60
+ silence_stream(STDOUT) do
61
+ TCPSocket.wait_for_service_with_timeout \
62
+ :host => (Webrat.configuration.selenium_server_address || "0.0.0.0"),
63
+ :port => Webrat.configuration.selenium_server_port,
64
+ :timeout => 15 # seconds
65
+ end
66
+ end
67
+
68
+ def fail
69
+ $stderr.puts
70
+ $stderr.puts
71
+ $stderr.puts "==> Failed to boot the Selenium RC server... exiting!"
72
+ exit
73
+ end
74
+
75
+ def stop
76
+ silence_stream(STDOUT) do
77
+ ::Selenium::RemoteControl::RemoteControl.new("0.0.0.0", Webrat.configuration.selenium_server_port, 5).stop
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,252 @@
1
+ require "webrat/core/save_and_open_page"
2
+ require "webrat/selenium/selenium_rc_server"
3
+ require "webrat/selenium/application_server_factory"
4
+ require "webrat/selenium/application_servers/base"
5
+
6
+ module Webrat
7
+ class TimeoutError < WebratError
8
+ end
9
+
10
+ class SeleniumResponse
11
+ attr_reader :body
12
+ attr_reader :session
13
+
14
+ def initialize(session, body)
15
+ @session = session
16
+ @body = body
17
+ end
18
+
19
+ def selenium
20
+ session.selenium
21
+ end
22
+ end
23
+
24
+ class SeleniumSession
25
+ include Webrat::SaveAndOpenPage
26
+ include Webrat::Selenium::SilenceStream
27
+
28
+ def initialize(*args) # :nodoc:
29
+ end
30
+
31
+ def simulate
32
+ end
33
+
34
+ def automate
35
+ yield
36
+ end
37
+
38
+ def visit(url)
39
+ selenium.open(url)
40
+ end
41
+
42
+ webrat_deprecate :visits, :visit
43
+
44
+ def fill_in(field_identifier, options)
45
+ locator = "webrat=#{field_identifier}"
46
+ selenium.wait_for_element locator, :timeout_in_seconds => 5
47
+ selenium.type(locator, "#{options[:with]}")
48
+ end
49
+
50
+ webrat_deprecate :fills_in, :fill_in
51
+
52
+ def response
53
+ SeleniumResponse.new(self, response_body)
54
+ end
55
+
56
+ def response_body #:nodoc:
57
+ selenium.get_html_source
58
+ end
59
+
60
+ def current_url
61
+ selenium.location
62
+ end
63
+
64
+ def click_button(button_text_or_regexp = nil, options = {})
65
+ if button_text_or_regexp.is_a?(Hash) && options == {}
66
+ pattern, options = nil, button_text_or_regexp
67
+ elsif button_text_or_regexp
68
+ pattern = adjust_if_regexp(button_text_or_regexp)
69
+ end
70
+ pattern ||= '*'
71
+ locator = "button=#{pattern}"
72
+
73
+ selenium.wait_for_element locator, :timeout_in_seconds => 5
74
+ selenium.click locator
75
+ end
76
+
77
+ webrat_deprecate :clicks_button, :click_button
78
+
79
+ def click_link(link_text_or_regexp, options = {})
80
+ pattern = adjust_if_regexp(link_text_or_regexp)
81
+ locator = "webratlink=#{pattern}"
82
+ selenium.wait_for_element locator, :timeout_in_seconds => 5
83
+ selenium.click locator
84
+ end
85
+
86
+ webrat_deprecate :clicks_link, :click_link
87
+
88
+ def click_link_within(selector, link_text, options = {})
89
+ locator = "webratlinkwithin=#{selector}|#{link_text}"
90
+ selenium.wait_for_element locator, :timeout_in_seconds => 5
91
+ selenium.click locator
92
+ end
93
+
94
+ webrat_deprecate :clicks_link_within, :click_link_within
95
+
96
+ def select(option_text, options = {})
97
+ id_or_name_or_label = options[:from]
98
+
99
+ if id_or_name_or_label
100
+ select_locator = "webrat=#{id_or_name_or_label}"
101
+ else
102
+ select_locator = "webratselectwithoption=#{option_text}"
103
+ end
104
+
105
+ selenium.wait_for_element select_locator, :timeout_in_seconds => 5
106
+ selenium.select(select_locator, option_text)
107
+ end
108
+
109
+ webrat_deprecate :selects, :select
110
+
111
+ def select_frame(selector)
112
+ remote_control_command("selectFrame", selector)
113
+ end
114
+
115
+ def choose(label_text)
116
+ locator = "webrat=#{label_text}"
117
+ selenium.wait_for_element locator, :timeout_in_seconds => 5
118
+ selenium.click locator
119
+ end
120
+
121
+ webrat_deprecate :chooses, :choose
122
+
123
+ def check(label_text)
124
+ locator = "webrat=#{label_text}"
125
+ selenium.wait_for_element locator, :timeout_in_seconds => 5
126
+ selenium.click locator
127
+ end
128
+ alias_method :uncheck, :check
129
+
130
+ webrat_deprecate :checks, :check
131
+
132
+ def fire_event(field_identifier, event)
133
+ locator = "webrat=#{Regexp.escape(field_identifier)}"
134
+ selenium.fire_event(locator, "#{event}")
135
+ end
136
+
137
+ def key_down(field_identifier, key_code)
138
+ locator = "webrat=#{Regexp.escape(field_identifier)}"
139
+ selenium.key_down(locator, key_code)
140
+ end
141
+
142
+ def key_up(field_identifier, key_code)
143
+ locator = "webrat=#{Regexp.escape(field_identifier)}"
144
+ selenium.key_up(locator, key_code)
145
+ end
146
+
147
+ def wait_for(params={})
148
+ timeout = params[:timeout] || 5
149
+ message = params[:message] || "Timeout exceeded"
150
+
151
+ begin_time = Time.now
152
+
153
+ while (Time.now - begin_time) < timeout
154
+ value = nil
155
+
156
+ begin
157
+ value = yield
158
+ rescue Exception => e
159
+ unless is_ignorable_wait_for_exception?(e)
160
+ raise e
161
+ end
162
+ end
163
+
164
+ return value if value
165
+
166
+ sleep 0.25
167
+ end
168
+
169
+ raise Webrat::TimeoutError.new(message + " (after #{timeout} sec)")
170
+ true
171
+ end
172
+
173
+ def selenium
174
+ return $browser if $browser
175
+ setup
176
+ $browser
177
+ end
178
+
179
+ webrat_deprecate :browser, :selenium
180
+
181
+
182
+ def save_and_open_screengrab
183
+ return unless File.exist?(saved_page_dir)
184
+
185
+ filename = "#{saved_page_dir}/webrat-#{Time.now.to_i}.png"
186
+
187
+ if $browser.chrome_backend?
188
+ $browser.capture_entire_page_screenshot(filename, '')
189
+ else
190
+ $browser.capture_screenshot(filename)
191
+ end
192
+ open_in_browser(filename)
193
+
194
+ end
195
+
196
+ protected
197
+ def is_ignorable_wait_for_exception?(exception) #:nodoc:
198
+ if defined?(::Spec::Expectations::ExpectationNotMetError)
199
+ return true if exception.class == ::Spec::Expectations::ExpectationNotMetError
200
+ end
201
+ return true if [::Selenium::CommandError, Webrat::WebratError].include?(exception.class)
202
+ return false
203
+ end
204
+
205
+ def setup #:nodoc:
206
+ Webrat::Selenium::SeleniumRCServer.boot
207
+ Webrat::Selenium::ApplicationServerFactory.app_server_instance.boot
208
+
209
+ create_browser
210
+ $browser.start
211
+
212
+ extend_selenium
213
+ define_location_strategies
214
+ $browser.window_maximize
215
+ end
216
+
217
+
218
+ def create_browser
219
+ $browser = ::Selenium::Client::Driver.new(Webrat.configuration.selenium_server_address || "localhost",
220
+ Webrat.configuration.selenium_server_port, Webrat.configuration.selenium_browser_key, "http://#{Webrat.configuration.application_address}:#{Webrat.configuration.application_port}")
221
+ $browser.set_speed(0) unless Webrat.configuration.selenium_server_address
222
+
223
+ at_exit do
224
+ silence_stream(STDOUT) do
225
+ $browser.stop
226
+ end
227
+ end
228
+ end
229
+
230
+ def adjust_if_regexp(text_or_regexp) #:nodoc:
231
+ if text_or_regexp.is_a?(Regexp)
232
+ "evalregex:#{text_or_regexp.inspect}"
233
+ else
234
+ "evalregex:/#{text_or_regexp}/"
235
+ end
236
+ end
237
+
238
+ def extend_selenium #:nodoc:
239
+ extensions_file = File.join(File.dirname(__FILE__), "selenium_extensions.js")
240
+ extenions_js = File.read(extensions_file)
241
+ selenium.get_eval(extenions_js)
242
+ end
243
+
244
+ def define_location_strategies #:nodoc:
245
+ Dir[File.join(File.dirname(__FILE__), "location_strategy_javascript", "*.js")].sort.each do |file|
246
+ strategy_js = File.read(file)
247
+ strategy_name = File.basename(file, '.js')
248
+ selenium.add_location_strategy(strategy_name, strategy_js)
249
+ end
250
+ end
251
+ end
252
+ end