benschwarz-webrat 0.3.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/History.txt +184 -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 +13 -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 +29 -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 +94 -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 +54 -0
  35. data/lib/webrat/core/mime.rb +29 -0
  36. data/lib/webrat/core/scope.rb +318 -0
  37. data/lib/webrat/core/session.rb +241 -0
  38. data/lib/webrat/core/xml.rb +99 -0
  39. data/lib/webrat/core/xml/hpricot.rb +19 -0
  40. data/lib/webrat/core/xml/nokogiri.rb +44 -0
  41. data/lib/webrat/core/xml/rexml.rb +24 -0
  42. data/lib/webrat/core_extensions/blank.rb +58 -0
  43. data/lib/webrat/core_extensions/deprecate.rb +8 -0
  44. data/lib/webrat/core_extensions/detect_mapped.rb +12 -0
  45. data/lib/webrat/core_extensions/hash_with_indifferent_access.rb +131 -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/mechanize.rb +43 -0
  49. data/lib/webrat/merb.rb +77 -0
  50. data/lib/webrat/rack.rb +26 -0
  51. data/lib/webrat/rails.rb +88 -0
  52. data/lib/webrat/rails/redirect_actions.rb +18 -0
  53. data/lib/webrat/rspec-rails.rb +13 -0
  54. data/lib/webrat/selenium.rb +58 -0
  55. data/lib/webrat/selenium/location_strategy_javascript/button.js +12 -0
  56. data/lib/webrat/selenium/location_strategy_javascript/label.js +16 -0
  57. data/lib/webrat/selenium/location_strategy_javascript/webrat.js +5 -0
  58. data/lib/webrat/selenium/location_strategy_javascript/webratlink.js +9 -0
  59. data/lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js +15 -0
  60. data/lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js +5 -0
  61. data/lib/webrat/selenium/selenium_extensions.js +6 -0
  62. data/lib/webrat/selenium/selenium_session.rb +186 -0
  63. data/lib/webrat/sinatra.rb +21 -0
  64. data/vendor/selenium-server.jar +0 -0
  65. metadata +144 -0
@@ -0,0 +1,77 @@
1
+ require "webrat"
2
+
3
+ require "cgi"
4
+ gem "extlib"
5
+ require "extlib"
6
+ require "merb-core"
7
+
8
+ HashWithIndifferentAccess = Mash
9
+
10
+ module Webrat
11
+ class MerbSession < Session #:nodoc:
12
+ include Merb::Test::MakeRequest
13
+
14
+ attr_accessor :response
15
+
16
+ def get(url, data, headers = nil)
17
+ do_request(url, data, headers, "GET")
18
+ end
19
+
20
+ def post(url, data, headers = nil)
21
+ do_request(url, data, headers, "POST")
22
+ end
23
+
24
+ def put(url, data, headers = nil)
25
+ do_request(url, data, headers, "PUT")
26
+ end
27
+
28
+ def delete(url, data, headers = nil)
29
+ do_request(url, data, headers, "DELETE")
30
+ end
31
+
32
+ def response_body
33
+ @response.body.to_s
34
+ end
35
+
36
+ def response_code
37
+ @response.status
38
+ end
39
+
40
+ def do_request(url, data, headers, method)
41
+ @response = request(url,
42
+ :params => (data && data.any?) ? data : nil,
43
+ :headers => headers,
44
+ :method => method)
45
+ follow_redirect
46
+ end
47
+
48
+ def follow_redirect
49
+ self.get(@response.headers['Location'], nil, @response.headers) if @response.status == 302
50
+ end
51
+
52
+ end
53
+ end
54
+
55
+ module Merb #:nodoc:
56
+ module Test #:nodoc:
57
+ module RequestHelper #:nodoc:
58
+ def request(uri, env = {})
59
+ @_webrat_session ||= Webrat::MerbSession.new
60
+ @_webrat_session.response = @_webrat_session.request(uri, env)
61
+ end
62
+
63
+ def follow_redirect
64
+ @_webrat_session.follow_redirect
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ class Merb::Test::RspecStory #:nodoc:
71
+ def browser
72
+ @browser ||= Webrat::MerbSession.new
73
+ end
74
+ end
75
+
76
+ Webrat.configuration.mode = :merb
77
+
@@ -0,0 +1,26 @@
1
+ require 'webrat'
2
+
3
+ class CGIMethods #:nodoc:
4
+ def self.parse_query_parameters(params)
5
+ hash = {}
6
+ params.split('&').each do |p|
7
+ pair = p.split('=')
8
+ hash[pair[0]] = pair[1]
9
+ end
10
+ hash
11
+ end
12
+ end
13
+
14
+ module Webrat
15
+ class RackSession < Session #:nodoc:
16
+ def response_body
17
+ @response.body
18
+ end
19
+
20
+ def response_code
21
+ @response.status
22
+ end
23
+ end
24
+ end
25
+
26
+ Webrat.configuration.mode = :rack
@@ -0,0 +1,88 @@
1
+ require "webrat"
2
+ require "action_controller/integration"
3
+
4
+ module Webrat
5
+ class RailsSession < Session #:nodoc:
6
+
7
+ def doc_root
8
+ File.expand_path(File.join(RAILS_ROOT, 'public'))
9
+ end
10
+
11
+ def saved_page_dir
12
+ File.expand_path(File.join(RAILS_ROOT, "tmp"))
13
+ end
14
+
15
+ def get(url, data, headers = nil)
16
+ do_request(:get, url, data, headers)
17
+ end
18
+
19
+ def post(url, data, headers = nil)
20
+ do_request(:post, url, data, headers)
21
+ end
22
+
23
+ def put(url, data, headers = nil)
24
+ do_request(:put, url, data, headers)
25
+ end
26
+
27
+ def delete(url, data, headers = nil)
28
+ do_request(:delete, url, data, headers)
29
+ end
30
+
31
+ def response_body
32
+ response.body
33
+ end
34
+
35
+ def response_code
36
+ response.code.to_i
37
+ end
38
+
39
+ protected
40
+
41
+ def integration_session
42
+ @context
43
+ end
44
+
45
+ def do_request(http_method, url, data, headers) #:nodoc:
46
+ update_protocol(url)
47
+ integration_session.request_via_redirect(http_method, remove_protocol(url), data, headers)
48
+ end
49
+
50
+ def remove_protocol(href) #:nodoc:
51
+ if href =~ %r{^https?://www.example.com(/.*)}
52
+ $LAST_MATCH_INFO.captures.first
53
+ else
54
+ href
55
+ end
56
+ end
57
+
58
+ def update_protocol(href) #:nodoc:
59
+ if href =~ /^https:/
60
+ integration_session.https!(true)
61
+ elsif href =~ /^http:/
62
+ integration_session.https!(false)
63
+ end
64
+ end
65
+
66
+ def response #:nodoc:
67
+ integration_session.response
68
+ end
69
+
70
+ end
71
+ end
72
+
73
+ module ActionController #:nodoc:
74
+ module Integration #:nodoc:
75
+ Session.class_eval do
76
+ unless instance_methods.include?("put_via_redirect")
77
+ require "webrat/rails/redirect_actions"
78
+ include Webrat::RedirectActions
79
+ end
80
+ end
81
+ end
82
+
83
+ IntegrationTest.class_eval do
84
+ include Webrat::Methods
85
+ end
86
+ end
87
+
88
+ Webrat.configuration.mode = :rails
@@ -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:
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,58 @@
1
+ require "webrat"
2
+ gem "selenium-client", ">=1.2.9"
3
+ require "selenium/client"
4
+ require "webrat/selenium/selenium_session"
5
+
6
+ Webrat.configuration.mode = :selenium
7
+
8
+ module Webrat
9
+
10
+ def self.with_selenium_server #:nodoc:
11
+ start_selenium_server
12
+ yield
13
+ stop_selenium_server
14
+ end
15
+
16
+ def self.start_selenium_server #:nodoc:
17
+ @remote_control ||= ::Selenium::RemoteControl::RemoteControl.new("0.0.0.0", 4444, 5)
18
+ @remote_control.jar_file = File.expand_path(__FILE__ + "../../../../vendor/selenium-server.jar")
19
+ @remote_control.start :background => true
20
+ TCPSocket.wait_for_service :host => "0.0.0.0", :port => 4444
21
+ end
22
+
23
+ def self.stop_selenium_server #:nodoc:
24
+ @remote_control.stop
25
+ end
26
+
27
+ def self.start_app_server #:nodoc:
28
+ pid_file = File.expand_path(RAILS_ROOT + "/tmp/pids/mongrel_selenium.pid")
29
+ system("mongrel_rails start -d --chdir=#{RAILS_ROOT} --port=3001 --environment=selenium --pid #{pid_file} &")
30
+ TCPSocket.wait_for_service :host => "0.0.0.0", :port => 3001
31
+ end
32
+
33
+ def self.stop_app_server #:nodoc:
34
+ pid_file = File.expand_path(RAILS_ROOT + "/tmp/pids/mongrel_selenium.pid")
35
+ system "mongrel_rails stop -c #{RAILS_ROOT} --pid #{pid_file}"
36
+ end
37
+
38
+ module Selenium #:nodoc:
39
+ module Rails #:nodoc:
40
+ class World < ::ActionController::IntegrationTest
41
+
42
+ def initialize #:nodoc:
43
+ @_result = Test::Unit::TestResult.new
44
+ end
45
+
46
+ end
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ module ::ActionController #:nodoc:
53
+ module Integration #:nodoc:
54
+ class Session #:nodoc:
55
+ include Webrat::Methods
56
+ end
57
+ end
58
+ 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,186 @@
1
+ module Webrat
2
+ class SeleniumSession
3
+
4
+ def initialize(*args) # :nodoc:
5
+ extend_selenium
6
+ define_location_strategies
7
+ end
8
+
9
+ def visit(url)
10
+ selenium.open(url)
11
+ end
12
+
13
+ webrat_deprecate :visits, :visit
14
+
15
+ def fill_in(field_identifier, options)
16
+ locator = "webrat=#{Regexp.escape(field_identifier)}"
17
+ selenium.type(locator, "#{options[:with]}")
18
+ end
19
+
20
+ webrat_deprecate :fills_in, :fill_in
21
+
22
+ def response_body #:nodoc:
23
+ selenium.get_html_source
24
+ end
25
+
26
+ def click_button(button_text_or_regexp = nil, options = {})
27
+ if button_text_or_regexp.is_a?(Hash) && options == {}
28
+ pattern, options = nil, button_text_or_regexp
29
+ else
30
+ pattern = adjust_if_regexp(button_text_or_regexp)
31
+ end
32
+ pattern ||= '*'
33
+ selenium.click("button=#{pattern}")
34
+ wait_for_result(options[:wait])
35
+ end
36
+
37
+ webrat_deprecate :clicks_button, :click_button
38
+
39
+ def click_link(link_text_or_regexp, options = {})
40
+ pattern = adjust_if_regexp(link_text_or_regexp)
41
+ selenium.click("webratlink=#{pattern}")
42
+ wait_for_result(options[:wait])
43
+ end
44
+
45
+ webrat_deprecate :clicks_link, :click_link
46
+
47
+ def click_link_within(selector, link_text, options = {})
48
+ selenium.click("webratlinkwithin=#{selector}|#{link_text}")
49
+ wait_for_result(options[:wait])
50
+ end
51
+
52
+ webrat_deprecate :clicks_link_within, :click_link_within
53
+
54
+ def wait_for_result(wait_type)
55
+ if wait_type == :ajax
56
+ wait_for_ajax
57
+ elsif wait_type == :effects
58
+ wait_for_effects
59
+ else
60
+ wait_for_page_to_load
61
+ end
62
+ end
63
+
64
+ def wait_for_page_to_load(timeout = 15000)
65
+ selenium.wait_for_page_to_load(timeout)
66
+ end
67
+
68
+ def wait_for_ajax(timeout = 15000)
69
+ selenium.wait_for_condition "Ajax.activeRequestCount == 0", timeout
70
+ end
71
+
72
+ def wait_for_effects(timeout = 15000)
73
+ selenium.wait_for_condition "window.Effect.Queue.size() == 0", timeout
74
+ end
75
+
76
+ def wait_for_ajax_and_effects
77
+ wait_for_ajax
78
+ wait_for_effects
79
+ end
80
+
81
+ def select(option_text, options = {})
82
+ id_or_name_or_label = options[:from]
83
+
84
+ if id_or_name_or_label
85
+ select_locator = "webrat=#{id_or_name_or_label}"
86
+ else
87
+ select_locator = "webratselectwithoption=#{option_text}"
88
+ end
89
+ selenium.select(select_locator, option_text)
90
+ end
91
+
92
+ webrat_deprecate :selects, :select
93
+
94
+ def choose(label_text)
95
+ selenium.click("webrat=#{label_text}")
96
+ end
97
+
98
+ webrat_deprecate :chooses, :choose
99
+
100
+ def check(label_text)
101
+ selenium.check("webrat=#{label_text}")
102
+ end
103
+
104
+ webrat_deprecate :checks, :check
105
+
106
+ def is_ordered(*args) #:nodoc:
107
+ selenium.is_ordered(*args)
108
+ end
109
+
110
+ def dragdrop(*args) #:nodoc:
111
+ selenium.dragdrop(*args)
112
+ end
113
+
114
+ def fire_event(field_identifier, event)
115
+ locator = "webrat=#{Regexp.escape(field_identifier)}"
116
+ selenium.fire_event(locator, "#{event}")
117
+ end
118
+
119
+ def key_down(field_identifier, key_code)
120
+ locator = "webrat=#{Regexp.escape(field_identifier)}"
121
+ selenium.key_down(locator, key_code)
122
+ end
123
+
124
+ def key_up(field_identifier, key_code)
125
+ locator = "webrat=#{Regexp.escape(field_identifier)}"
126
+ selenium.key_up(locator, key_code)
127
+ end
128
+
129
+ def browser
130
+ return $browser if $browser
131
+ setup
132
+ $browser
133
+ end
134
+
135
+ protected
136
+
137
+ def setup #:nodoc:
138
+ silence_stream(STDOUT) do
139
+ Webrat.start_selenium_server
140
+ Webrat.start_app_server
141
+ end
142
+
143
+
144
+ $browser = ::Selenium::Client::Driver.new("localhost", 4444, "*firefox", "http://0.0.0.0:3001")
145
+ $browser.set_speed(0)
146
+ $browser.start
147
+ teardown_at_exit
148
+ end
149
+
150
+ def selenium #:nodoc:
151
+ browser
152
+ end
153
+
154
+ def teardown_at_exit #:nodoc:
155
+ at_exit do
156
+ silence_stream(STDOUT) do
157
+ $browser.stop
158
+ Webrat.stop_app_server
159
+ Webrat.stop_selenium_server
160
+ end
161
+ end
162
+ end
163
+
164
+ def adjust_if_regexp(text_or_regexp) #:nodoc:
165
+ if text_or_regexp.is_a?(Regexp)
166
+ "evalregex:#{text_or_regexp.inspect}"
167
+ else
168
+ text_or_regexp
169
+ end
170
+ end
171
+
172
+ def extend_selenium #:nodoc:
173
+ extensions_file = File.join(File.dirname(__FILE__), "selenium_extensions.js")
174
+ extenions_js = File.read(extensions_file)
175
+ selenium.get_eval(extenions_js)
176
+ end
177
+
178
+ def define_location_strategies #:nodoc:
179
+ Dir[File.join(File.dirname(__FILE__), "location_strategy_javascript", "*.js")].sort.each do |file|
180
+ strategy_js = File.read(file)
181
+ strategy_name = File.basename(file, '.js')
182
+ selenium.add_location_strategy(strategy_name, strategy_js)
183
+ end
184
+ end
185
+ end
186
+ end