aslakhellesoy-webrat 0.3.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/History.txt +193 -0
  2. data/MIT-LICENSE.txt +19 -0
  3. data/README.rdoc +81 -0
  4. data/Rakefile +104 -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 +44 -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 +386 -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 +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 +50 -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 +55 -0
  31. data/lib/webrat/core/matchers/have_selector.rb +37 -0
  32. data/lib/webrat/core/matchers/have_tag.rb +57 -0
  33. data/lib/webrat/core/matchers/have_xpath.rb +83 -0
  34. data/lib/webrat/core/methods.rb +60 -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 +330 -0
  38. data/lib/webrat/core/session.rb +218 -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 +43 -0
  50. data/lib/webrat/merb.rb +77 -0
  51. data/lib/webrat/rack.rb +26 -0
  52. data/lib/webrat/rails.rb +96 -0
  53. data/lib/webrat/rails/redirect_actions.rb +18 -0
  54. data/lib/webrat/rspec-rails.rb +13 -0
  55. data/lib/webrat/selenium.rb +107 -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/selenium_extensions.js +6 -0
  63. data/lib/webrat/selenium/selenium_session.rb +230 -0
  64. data/lib/webrat/sinatra.rb +21 -0
  65. data/vendor/selenium-server.jar +0 -0
  66. metadata +136 -0
@@ -0,0 +1,18 @@
1
+ # For Rails before http://dev.rubyonrails.org/ticket/10497 was committed
2
+ module Webrat
3
+ module RedirectActions #:nodoc:
4
+
5
+ def put_via_redirect(path, parameters = {}, headers = {})
6
+ put path, parameters, headers
7
+ follow_redirect! while redirect?
8
+ status
9
+ end
10
+
11
+ def delete_via_redirect(path, parameters = {}, headers = {})
12
+ delete path, parameters, headers
13
+ follow_redirect! while redirect?
14
+ status
15
+ end
16
+
17
+ end
18
+ end
@@ -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,107 @@
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
+ Webrat.configuration.mode = :selenium
8
+
9
+ module Webrat
10
+
11
+ def self.with_selenium_server #:nodoc:
12
+ start_selenium_server
13
+ yield
14
+ stop_selenium_server
15
+ end
16
+
17
+ def self.start_selenium_server #:nodoc:
18
+ remote_control = ::Selenium::RemoteControl::RemoteControl.new("0.0.0.0", 4444, 5)
19
+ remote_control.jar_file = File.expand_path(__FILE__ + "../../../../vendor/selenium-server.jar")
20
+ remote_control.start :background => true
21
+ TCPSocket.wait_for_service :host => "0.0.0.0", :port => 4444
22
+ end
23
+
24
+ def self.stop_selenium_server #:nodoc:
25
+ remote_control = ::Selenium::RemoteControl::RemoteControl.new("0.0.0.0", 4444, 5)
26
+ remote_control.stop
27
+ end
28
+
29
+ def self.start_app_server #:nodoc:
30
+ pid_file = File.expand_path(RAILS_ROOT + "/tmp/pids/mongrel_selenium.pid")
31
+ system("mongrel_rails start -d --chdir=#{RAILS_ROOT} --port=3001 --environment=selenium --pid #{pid_file} &")
32
+ TCPSocket.wait_for_service :host => "0.0.0.0", :port => 3001
33
+ end
34
+
35
+ def self.stop_app_server #:nodoc:
36
+ pid_file = File.expand_path(RAILS_ROOT + "/tmp/pids/mongrel_selenium.pid")
37
+ system "mongrel_rails stop -c #{RAILS_ROOT} --pid #{pid_file}"
38
+ end
39
+
40
+ # To use Webrat's Selenium support, you'll need the selenium-client gem installed.
41
+ # Activate it with (for example, in your <tt>env.rb</tt>):
42
+ #
43
+ # require "webrat/selenium"
44
+ #
45
+ # Then, if you're using Cucumber, configure it to use a
46
+ # <tt>Webrat::Selenium::Rails::World</tt> as the scenario context by adding
47
+ # the following to <tt>env.rb</tt>:
48
+ #
49
+ # World do
50
+ # Webrat::Selenium::Rails::World.new
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
+
78
+ module Rails #:nodoc:
79
+ class World < ::ActionController::IntegrationTest
80
+ include Webrat::Selenium::Matchers
81
+
82
+ def initialize #:nodoc:
83
+ @_result = Test::Unit::TestResult.new
84
+ end
85
+
86
+ def response
87
+ webrat_session.response
88
+ end
89
+
90
+ def wait_for(*args, &block)
91
+ webrat_session.wait_for(*args, &block)
92
+ end
93
+
94
+ def save_and_open_screengrab
95
+ webrat_session.save_and_open_screengrab
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ end
102
+
103
+ module ActionController #:nodoc:
104
+ IntegrationTest.class_eval do
105
+ include Webrat::Methods
106
+ end
107
+ 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,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,230 @@
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.check locator
115
+ end
116
+
117
+ webrat_deprecate :checks, :check
118
+
119
+ def fire_event(field_identifier, event)
120
+ locator = "webrat=#{Regexp.escape(field_identifier)}"
121
+ selenium.fire_event(locator, "#{event}")
122
+ end
123
+
124
+ def key_down(field_identifier, key_code)
125
+ locator = "webrat=#{Regexp.escape(field_identifier)}"
126
+ selenium.key_down(locator, key_code)
127
+ end
128
+
129
+ def key_up(field_identifier, key_code)
130
+ locator = "webrat=#{Regexp.escape(field_identifier)}"
131
+ selenium.key_up(locator, key_code)
132
+ end
133
+
134
+ def wait_for(params={})
135
+ timeout = params[:timeout] || 5
136
+ message = params[:message] || "Timeout exceeded"
137
+
138
+ begin_time = Time.now
139
+
140
+ while (Time.now - begin_time) < timeout
141
+ value = nil
142
+
143
+ begin
144
+ value = yield
145
+ rescue ::Spec::Expectations::ExpectationNotMetError, ::Selenium::CommandError, Webrat::WebratError
146
+ value = nil
147
+ end
148
+
149
+ return value if value
150
+
151
+ sleep 0.25
152
+ end
153
+
154
+ raise Webrat::TimeoutError.new(message + " (after #{timeout} sec)")
155
+ true
156
+ end
157
+
158
+ def selenium
159
+ return $browser if $browser
160
+ setup
161
+ $browser
162
+ end
163
+
164
+ webrat_deprecate :browser, :selenium
165
+
166
+
167
+ def save_and_open_screengrab
168
+ return unless File.exist?(saved_page_dir)
169
+
170
+ filename = "#{saved_page_dir}/webrat-#{Time.now.to_i}.png"
171
+
172
+ if $browser.chrome_backend?
173
+ $browser.capture_entire_page_screenshot(filename, '')
174
+ else
175
+ $browser.capture_screenshot(filename)
176
+ end
177
+ open_in_browser(filename)
178
+ end
179
+
180
+ protected
181
+
182
+ def setup #:nodoc:
183
+ silence_stream(STDOUT) do
184
+ Webrat.start_selenium_server
185
+ Webrat.start_app_server
186
+ end
187
+
188
+ $browser = ::Selenium::Client::Driver.new("localhost", 4444, "*firefox", "http://0.0.0.0:3001")
189
+ $browser.set_speed(0)
190
+ $browser.start
191
+ teardown_at_exit
192
+
193
+ extend_selenium
194
+ define_location_strategies
195
+ $browser.window_maximize
196
+ end
197
+
198
+ def teardown_at_exit #:nodoc:
199
+ at_exit do
200
+ silence_stream(STDOUT) do
201
+ $browser.stop
202
+ Webrat.stop_app_server
203
+ Webrat.stop_selenium_server
204
+ end
205
+ end
206
+ end
207
+
208
+ def adjust_if_regexp(text_or_regexp) #:nodoc:
209
+ if text_or_regexp.is_a?(Regexp)
210
+ "evalregex:#{text_or_regexp.inspect}"
211
+ else
212
+ "evalregex:/#{text_or_regexp}/"
213
+ end
214
+ end
215
+
216
+ def extend_selenium #:nodoc:
217
+ extensions_file = File.join(File.dirname(__FILE__), "selenium_extensions.js")
218
+ extenions_js = File.read(extensions_file)
219
+ selenium.get_eval(extenions_js)
220
+ end
221
+
222
+ def define_location_strategies #:nodoc:
223
+ Dir[File.join(File.dirname(__FILE__), "location_strategy_javascript", "*.js")].sort.each do |file|
224
+ strategy_js = File.read(file)
225
+ strategy_name = File.basename(file, '.js')
226
+ selenium.add_location_strategy(strategy_name, strategy_js)
227
+ end
228
+ end
229
+ end
230
+ end