auxesis-webrat 0.4.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 (67) hide show
  1. data/History.txt +264 -0
  2. data/MIT-LICENSE.txt +19 -0
  3. data/README.rdoc +85 -0
  4. data/Rakefile +151 -0
  5. data/install.rb +1 -0
  6. data/lib/webrat.rb +34 -0
  7. data/lib/webrat/core.rb +14 -0
  8. data/lib/webrat/core/configuration.rb +89 -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 +404 -0
  12. data/lib/webrat/core/elements/form.rb +132 -0
  13. data/lib/webrat/core/elements/label.rb +31 -0
  14. data/lib/webrat/core/elements/link.rb +90 -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 +66 -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 +21 -0
  29. data/lib/webrat/core/matchers.rb +4 -0
  30. data/lib/webrat/core/matchers/have_content.rb +69 -0
  31. data/lib/webrat/core/matchers/have_selector.rb +52 -0
  32. data/lib/webrat/core/matchers/have_tag.rb +71 -0
  33. data/lib/webrat/core/matchers/have_xpath.rb +93 -0
  34. data/lib/webrat/core/methods.rb +61 -0
  35. data/lib/webrat/core/mime.rb +29 -0
  36. data/lib/webrat/core/save_and_open_page.rb +50 -0
  37. data/lib/webrat/core/scope.rb +350 -0
  38. data/lib/webrat/core/session.rb +259 -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/hash_with_indifferent_access.rb +131 -0
  47. data/lib/webrat/core_extensions/meta_class.rb +6 -0
  48. data/lib/webrat/core_extensions/nil_to_param.rb +5 -0
  49. data/lib/webrat/mechanize.rb +74 -0
  50. data/lib/webrat/merb.rb +9 -0
  51. data/lib/webrat/merb_session.rb +73 -0
  52. data/lib/webrat/rack.rb +24 -0
  53. data/lib/webrat/rails.rb +105 -0
  54. data/lib/webrat/rspec-rails.rb +13 -0
  55. data/lib/webrat/selenium.rb +99 -0
  56. data/lib/webrat/selenium/location_strategy_javascript/button.js +12 -0
  57. data/lib/webrat/selenium/location_strategy_javascript/label.js +16 -0
  58. data/lib/webrat/selenium/location_strategy_javascript/webrat.js +5 -0
  59. data/lib/webrat/selenium/location_strategy_javascript/webratlink.js +9 -0
  60. data/lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js +15 -0
  61. data/lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js +5 -0
  62. data/lib/webrat/selenium/matchers.rb +4 -0
  63. data/lib/webrat/selenium/selenium_extensions.js +6 -0
  64. data/lib/webrat/selenium/selenium_session.rb +237 -0
  65. data/lib/webrat/sinatra.rb +30 -0
  66. data/vendor/selenium-server.jar +0 -0
  67. metadata +136 -0
@@ -0,0 +1,13 @@
1
+ # Supports using the matchers in controller, helper, and view specs if you're
2
+ # using rspec-rails. Just add a require statement to spec/spec_helper.rb or env.rb:
3
+ #
4
+ # require 'webrat/rspec-rails'
5
+ #
6
+ require "webrat/core/matchers"
7
+
8
+ Spec::Runner.configure do |config|
9
+ # rspec should support :type => [:controller, :helper, :view] - but until it does ...
10
+ config.include(Webrat::Matchers, :type => :controller)
11
+ config.include(Webrat::Matchers, :type => :helper)
12
+ config.include(Webrat::Matchers, :type => :view)
13
+ end
@@ -0,0 +1,99 @@
1
+ require "webrat"
2
+ gem "selenium-client", ">=1.2.9"
3
+ require "selenium/client"
4
+ require "webrat/selenium/selenium_session"
5
+ require "webrat/selenium/matchers"
6
+
7
+ module Webrat
8
+
9
+ def self.with_selenium_server #:nodoc:
10
+ start_selenium_server
11
+ yield
12
+ stop_selenium_server
13
+ end
14
+
15
+ def self.start_selenium_server #:nodoc:
16
+ unless Webrat.configuration.selenium_server_address
17
+ remote_control = ::Selenium::RemoteControl::RemoteControl.new("0.0.0.0", Webrat.configuration.selenium_server_port, 5)
18
+ remote_control.jar_file = File.expand_path(__FILE__ + "../../../../vendor/selenium-server.jar")
19
+ remote_control.start :background => true
20
+ end
21
+ TCPSocket.wait_for_service :host => (Webrat.configuration.selenium_server_address || "0.0.0.0"), :port => Webrat.configuration.selenium_server_port
22
+ end
23
+
24
+ def self.stop_selenium_server #:nodoc:
25
+ ::Selenium::RemoteControl::RemoteControl.new("0.0.0.0", Webrat.configuration.selenium_server_port, 5).stop unless Webrat.configuration.selenium_server_address
26
+ end
27
+
28
+ def self.start_app_server #:nodoc:
29
+ pid_file = prepare_pid_file("#{RAILS_ROOT}/tmp/pids", "mongrel_selenium.pid")
30
+ system("mongrel_rails start -d --chdir=#{RAILS_ROOT} --port=#{Webrat.configuration.application_port} --environment=#{Webrat.configuration.application_environment} --pid #{pid_file} &")
31
+ TCPSocket.wait_for_service :host => Webrat.configuration.application_address, :port => Webrat.configuration.application_port.to_i
32
+ end
33
+
34
+ def self.stop_app_server #:nodoc:
35
+ pid_file = File.expand_path(RAILS_ROOT + "/tmp/pids/mongrel_selenium.pid")
36
+ system "mongrel_rails stop -c #{RAILS_ROOT} --pid #{pid_file}"
37
+ end
38
+
39
+ def self.prepare_pid_file(file_path, pid_file_name)
40
+ FileUtils.mkdir_p File.expand_path(file_path)
41
+ File.expand_path("#{file_path}/#{pid_file_name}")
42
+ end
43
+
44
+ # To use Webrat's Selenium support, you'll need the selenium-client gem installed.
45
+ # Activate it with (for example, in your <tt>env.rb</tt>):
46
+ #
47
+ # require "webrat"
48
+ #
49
+ # Webrat.configure do |config|
50
+ # config.mode = :selenium
51
+ # end
52
+ #
53
+ # == Dropping down to the selenium-client API
54
+ #
55
+ # If you ever need to do something with Selenium not provided in the Webrat API,
56
+ # you can always drop down to the selenium-client API using the <tt>selenium</tt> method.
57
+ # For example:
58
+ #
59
+ # When "I drag the photo to the left" do
60
+ # selenium.dragdrop("id=photo_123", "+350, 0")
61
+ # end
62
+ #
63
+ # == Auto-starting of the mongrel and java server
64
+ #
65
+ # Webrat will automatically start the Selenium Java server process and an instance
66
+ # of Mongrel when a test is run. The Mongrel will run in the "selenium" environment
67
+ # instead of "test", so ensure you've got that defined, and will run on port 3001.
68
+ #
69
+ # == Waiting
70
+ #
71
+ # In order to make writing Selenium tests as easy as possible, Webrat will automatically
72
+ # wait for the correct elements to exist on the page when trying to manipulate them
73
+ # with methods like <tt>fill_in</tt>, etc. In general, this means you should be able to write
74
+ # your Webrat::Selenium tests ignoring the concurrency issues that can plague in-browser
75
+ # testing, so long as you're using the Webrat API.
76
+ module Selenium
77
+ module Methods
78
+ def response
79
+ webrat_session.response
80
+ end
81
+
82
+ def wait_for(*args, &block)
83
+ webrat_session.wait_for(*args, &block)
84
+ end
85
+
86
+ def save_and_open_screengrab
87
+ webrat_session.save_and_open_screengrab
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ module ActionController #:nodoc:
94
+ IntegrationTest.class_eval do
95
+ include Webrat::Methods
96
+ include Webrat::Selenium::Methods
97
+ include Webrat::Selenium::Matchers
98
+ end
99
+ end
@@ -0,0 +1,12 @@
1
+ if (locator == '*') {
2
+ return selenium.browserbot.locationStrategies['xpath'].call(this, "//input[@type='submit']", inDocument, inWindow)
3
+ }
4
+ var inputs = inDocument.getElementsByTagName('input');
5
+ return $A(inputs).find(function(candidate){
6
+ inputType = candidate.getAttribute('type');
7
+ if (inputType == 'submit' || inputType == 'image') {
8
+ var buttonText = $F(candidate);
9
+ return (PatternMatcher.matches(locator, buttonText));
10
+ }
11
+ return false;
12
+ });
@@ -0,0 +1,16 @@
1
+ var allLabels = inDocument.getElementsByTagName("label");
2
+ var candidateLabels = $A(allLabels).select(function(candidateLabel){
3
+ var regExp = new RegExp('^' + locator + '\\b', 'i');
4
+ var labelText = getText(candidateLabel).strip();
5
+ return (labelText.search(regExp) >= 0);
6
+ });
7
+ if (candidateLabels.length == 0) {
8
+ return null;
9
+ }
10
+ candidateLabels = candidateLabels.sortBy(function(s) { return s.length * -1; }); //reverse length sort
11
+ var locatedLabel = candidateLabels.first();
12
+ var labelFor = locatedLabel.getAttribute('for');
13
+ if ((labelFor == null) && (locatedLabel.hasChildNodes())) {
14
+ return locatedLabel.firstChild; //TODO: should find the first form field, not just any node
15
+ }
16
+ return selenium.browserbot.locationStrategies['id'].call(this, labelFor, inDocument, inWindow);
@@ -0,0 +1,5 @@
1
+ var locationStrategies = selenium.browserbot.locationStrategies;
2
+ return locationStrategies['id'].call(this, locator, inDocument, inWindow)
3
+ || locationStrategies['name'].call(this, locator, inDocument, inWindow)
4
+ || locationStrategies['label'].call(this, locator, inDocument, inWindow)
5
+ || null;
@@ -0,0 +1,9 @@
1
+ var links = inDocument.getElementsByTagName('a');
2
+ var candidateLinks = $A(links).select(function(candidateLink) {
3
+ return PatternMatcher.matches(locator, getText(candidateLink));
4
+ });
5
+ if (candidateLinks.length == 0) {
6
+ return null;
7
+ }
8
+ candidateLinks = candidateLinks.sortBy(function(s) { return s.length * -1; }); //reverse length sort
9
+ return candidateLinks.first();
@@ -0,0 +1,15 @@
1
+ var locatorParts = locator.split('|');
2
+ var cssAncestor = locatorParts[0];
3
+ var linkText = locatorParts[1];
4
+ var matchingElements = cssQuery(cssAncestor, inDocument);
5
+ var candidateLinks = matchingElements.collect(function(ancestor){
6
+ var links = ancestor.getElementsByTagName('a');
7
+ return $A(links).select(function(candidateLink) {
8
+ return PatternMatcher.matches(linkText, getText(candidateLink));
9
+ });
10
+ }).flatten().compact();
11
+ if (candidateLinks.length == 0) {
12
+ return null;
13
+ }
14
+ candidateLinks = candidateLinks.sortBy(function(s) { return s.length * -1; }); //reverse length sort
15
+ return candidateLinks.first();
@@ -0,0 +1,5 @@
1
+ var optionElements = inDocument.getElementsByTagName('option');
2
+ var locatedOption = $A(optionElements).find(function(candidate){
3
+ return (PatternMatcher.matches(locator, getText(candidate)));
4
+ });
5
+ return locatedOption ? locatedOption.parentNode : null;
@@ -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,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,237 @@
1
+ require "webrat/core/save_and_open_page"
2
+
3
+ module Webrat
4
+ class TimeoutError < WebratError
5
+ end
6
+
7
+ class SeleniumResponse
8
+ attr_reader :body
9
+ attr_reader :session
10
+
11
+ def initialize(session, body)
12
+ @session = session
13
+ @body = body
14
+ end
15
+
16
+ def selenium
17
+ session.selenium
18
+ end
19
+ end
20
+
21
+ class SeleniumSession
22
+ include Webrat::SaveAndOpenPage
23
+
24
+ def initialize(*args) # :nodoc:
25
+ end
26
+
27
+ def simulate
28
+ end
29
+
30
+ def automate
31
+ yield
32
+ end
33
+
34
+ def visit(url)
35
+ selenium.open(url)
36
+ end
37
+
38
+ webrat_deprecate :visits, :visit
39
+
40
+ def fill_in(field_identifier, options)
41
+ locator = "webrat=#{Regexp.escape(field_identifier)}"
42
+ selenium.wait_for_element locator, 5
43
+ selenium.type(locator, "#{options[:with]}")
44
+ end
45
+
46
+ webrat_deprecate :fills_in, :fill_in
47
+
48
+ def response
49
+ SeleniumResponse.new(self, response_body)
50
+ end
51
+
52
+ def response_body #:nodoc:
53
+ selenium.get_html_source
54
+ end
55
+
56
+ def click_button(button_text_or_regexp = nil, options = {})
57
+ if button_text_or_regexp.is_a?(Hash) && options == {}
58
+ pattern, options = nil, button_text_or_regexp
59
+ elsif button_text_or_regexp
60
+ pattern = adjust_if_regexp(button_text_or_regexp)
61
+ end
62
+ pattern ||= '*'
63
+ locator = "button=#{pattern}"
64
+
65
+ selenium.wait_for_element locator, 5
66
+ selenium.click locator
67
+ end
68
+
69
+ webrat_deprecate :clicks_button, :click_button
70
+
71
+ def click_link(link_text_or_regexp, options = {})
72
+ pattern = adjust_if_regexp(link_text_or_regexp)
73
+ locator = "webratlink=#{pattern}"
74
+ selenium.wait_for_element locator, 5
75
+ selenium.click locator
76
+ end
77
+
78
+ webrat_deprecate :clicks_link, :click_link
79
+
80
+ def click_link_within(selector, link_text, options = {})
81
+ locator = "webratlinkwithin=#{selector}|#{link_text}"
82
+ selenium.wait_for_element locator, 5
83
+ selenium.click locator
84
+ end
85
+
86
+ webrat_deprecate :clicks_link_within, :click_link_within
87
+
88
+ def select(option_text, options = {})
89
+ id_or_name_or_label = options[:from]
90
+
91
+ if id_or_name_or_label
92
+ select_locator = "webrat=#{id_or_name_or_label}"
93
+ else
94
+ select_locator = "webratselectwithoption=#{option_text}"
95
+ end
96
+
97
+ selenium.wait_for_element select_locator, 5
98
+ selenium.select(select_locator, option_text)
99
+ end
100
+
101
+ webrat_deprecate :selects, :select
102
+
103
+ def choose(label_text)
104
+ locator = "webrat=#{label_text}"
105
+ selenium.wait_for_element locator, 5
106
+ selenium.click locator
107
+ end
108
+
109
+ webrat_deprecate :chooses, :choose
110
+
111
+ def check(label_text)
112
+ locator = "webrat=#{label_text}"
113
+ selenium.wait_for_element locator, 5
114
+ selenium.click locator
115
+ end
116
+ alias_method :uncheck, :check
117
+
118
+ webrat_deprecate :checks, :check
119
+
120
+ def fire_event(field_identifier, event)
121
+ locator = "webrat=#{Regexp.escape(field_identifier)}"
122
+ selenium.fire_event(locator, "#{event}")
123
+ end
124
+
125
+ def key_down(field_identifier, key_code)
126
+ locator = "webrat=#{Regexp.escape(field_identifier)}"
127
+ selenium.key_down(locator, key_code)
128
+ end
129
+
130
+ def key_up(field_identifier, key_code)
131
+ locator = "webrat=#{Regexp.escape(field_identifier)}"
132
+ selenium.key_up(locator, key_code)
133
+ end
134
+
135
+ def wait_for(params={})
136
+ timeout = params[:timeout] || 5
137
+ message = params[:message] || "Timeout exceeded"
138
+
139
+ begin_time = Time.now
140
+
141
+ while (Time.now - begin_time) < timeout
142
+ value = nil
143
+
144
+ begin
145
+ value = yield
146
+ rescue ::Spec::Expectations::ExpectationNotMetError, ::Selenium::CommandError, Webrat::WebratError
147
+ value = nil
148
+ end
149
+
150
+ return value if value
151
+
152
+ sleep 0.25
153
+ end
154
+
155
+ raise Webrat::TimeoutError.new(message + " (after #{timeout} sec)")
156
+ true
157
+ end
158
+
159
+ def selenium
160
+ return $browser if $browser
161
+ setup
162
+ $browser
163
+ end
164
+
165
+ webrat_deprecate :browser, :selenium
166
+
167
+
168
+ def save_and_open_screengrab
169
+ return unless File.exist?(saved_page_dir)
170
+
171
+ filename = "#{saved_page_dir}/webrat-#{Time.now.to_i}.png"
172
+
173
+ if $browser.chrome_backend?
174
+ $browser.capture_entire_page_screenshot(filename, '')
175
+ else
176
+ $browser.capture_screenshot(filename)
177
+ end
178
+ open_in_browser(filename)
179
+ end
180
+
181
+ protected
182
+
183
+ def setup #:nodoc:
184
+ silence_stream(STDOUT) do
185
+ Webrat.start_selenium_server
186
+ Webrat.start_app_server
187
+ end
188
+
189
+ create_browser
190
+ $browser.start
191
+ teardown_at_exit
192
+
193
+ extend_selenium
194
+ define_location_strategies
195
+ $browser.window_maximize
196
+ end
197
+
198
+
199
+ def create_browser
200
+ $browser = ::Selenium::Client::Driver.new(Webrat.configuration.selenium_server_address || "localhost",
201
+ Webrat.configuration.selenium_server_port, Webrat.configuration.selenium_browser_key, "http://#{Webrat.configuration.application_address}:#{Webrat.configuration.application_port}")
202
+ $browser.set_speed(0) unless Webrat.configuration.selenium_server_address
203
+ end
204
+
205
+ def teardown_at_exit #:nodoc:
206
+ at_exit do
207
+ silence_stream(STDOUT) do
208
+ $browser.stop
209
+ Webrat.stop_app_server
210
+ Webrat.stop_selenium_server
211
+ end
212
+ end
213
+ end
214
+
215
+ def adjust_if_regexp(text_or_regexp) #:nodoc:
216
+ if text_or_regexp.is_a?(Regexp)
217
+ "evalregex:#{text_or_regexp.inspect}"
218
+ else
219
+ "evalregex:/#{text_or_regexp}/"
220
+ end
221
+ end
222
+
223
+ def extend_selenium #:nodoc:
224
+ extensions_file = File.join(File.dirname(__FILE__), "selenium_extensions.js")
225
+ extenions_js = File.read(extensions_file)
226
+ selenium.get_eval(extenions_js)
227
+ end
228
+
229
+ def define_location_strategies #:nodoc:
230
+ Dir[File.join(File.dirname(__FILE__), "location_strategy_javascript", "*.js")].sort.each do |file|
231
+ strategy_js = File.read(file)
232
+ strategy_name = File.basename(file, '.js')
233
+ selenium.add_location_strategy(strategy_name, strategy_js)
234
+ end
235
+ end
236
+ end
237
+ end
@@ -0,0 +1,30 @@
1
+ require 'webrat/rack'
2
+ require 'sinatra'
3
+ require 'sinatra/test'
4
+
5
+ class Sinatra::Application
6
+ # Override this to prevent Sinatra from barfing on the options passed from RSpec
7
+ def self.load_default_options_from_command_line!
8
+ end
9
+ end
10
+
11
+ disable :run
12
+ disable :reload
13
+
14
+ module Webrat
15
+ class SinatraSession < RackSession #:nodoc:
16
+ include Sinatra::Test
17
+
18
+ attr_reader :request, :response
19
+
20
+ %w(get head post put delete).each do |verb|
21
+ alias_method "orig_#{verb}", verb
22
+ define_method(verb) do |*args| # (path, data, headers = nil)
23
+ path, data, headers = *args
24
+ data = data.inject({}) {|data, (key,value)| data[key] = Rack::Utils.unescape(value); data }
25
+ params = data.merge(:env => headers || {})
26
+ self.__send__("orig_#{verb}", path, params)
27
+ end
28
+ end
29
+ end
30
+ end