futuresinc-webrat 0.4.4.99
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.
- data/History.txt +333 -0
- data/MIT-LICENSE.txt +19 -0
- data/README.rdoc +85 -0
- data/Rakefile +156 -0
- data/install.rb +1 -0
- data/lib/webrat/core/configuration.rb +98 -0
- data/lib/webrat/core/elements/area.rb +31 -0
- data/lib/webrat/core/elements/element.rb +33 -0
- data/lib/webrat/core/elements/field.rb +403 -0
- data/lib/webrat/core/elements/form.rb +103 -0
- data/lib/webrat/core/elements/label.rb +31 -0
- data/lib/webrat/core/elements/link.rb +92 -0
- data/lib/webrat/core/elements/select_option.rb +35 -0
- data/lib/webrat/core/locators/area_locator.rb +38 -0
- data/lib/webrat/core/locators/button_locator.rb +54 -0
- data/lib/webrat/core/locators/field_by_id_locator.rb +37 -0
- data/lib/webrat/core/locators/field_labeled_locator.rb +56 -0
- data/lib/webrat/core/locators/field_locator.rb +25 -0
- data/lib/webrat/core/locators/field_named_locator.rb +41 -0
- data/lib/webrat/core/locators/form_locator.rb +19 -0
- data/lib/webrat/core/locators/label_locator.rb +34 -0
- data/lib/webrat/core/locators/link_locator.rb +66 -0
- data/lib/webrat/core/locators/locator.rb +20 -0
- data/lib/webrat/core/locators/select_option_locator.rb +59 -0
- data/lib/webrat/core/locators.rb +20 -0
- data/lib/webrat/core/logging.rb +21 -0
- data/lib/webrat/core/matchers/have_content.rb +73 -0
- data/lib/webrat/core/matchers/have_selector.rb +74 -0
- data/lib/webrat/core/matchers/have_tag.rb +21 -0
- data/lib/webrat/core/matchers/have_xpath.rb +147 -0
- data/lib/webrat/core/matchers.rb +4 -0
- data/lib/webrat/core/methods.rb +61 -0
- data/lib/webrat/core/mime.rb +29 -0
- data/lib/webrat/core/save_and_open_page.rb +50 -0
- data/lib/webrat/core/scope.rb +350 -0
- data/lib/webrat/core/session.rb +281 -0
- data/lib/webrat/core/xml/hpricot.rb +19 -0
- data/lib/webrat/core/xml/nokogiri.rb +76 -0
- data/lib/webrat/core/xml/rexml.rb +24 -0
- data/lib/webrat/core/xml.rb +115 -0
- data/lib/webrat/core.rb +14 -0
- data/lib/webrat/core_extensions/blank.rb +58 -0
- data/lib/webrat/core_extensions/deprecate.rb +8 -0
- data/lib/webrat/core_extensions/detect_mapped.rb +12 -0
- data/lib/webrat/core_extensions/meta_class.rb +6 -0
- data/lib/webrat/core_extensions/nil_to_param.rb +5 -0
- data/lib/webrat/core_extensions/tcp_socket.rb +27 -0
- data/lib/webrat/mechanize.rb +74 -0
- data/lib/webrat/merb.rb +9 -0
- data/lib/webrat/merb_session.rb +65 -0
- data/lib/webrat/rack.rb +24 -0
- data/lib/webrat/rails.rb +105 -0
- data/lib/webrat/rspec-rails.rb +13 -0
- data/lib/webrat/selenium/application_server.rb +71 -0
- data/lib/webrat/selenium/location_strategy_javascript/button.js +12 -0
- data/lib/webrat/selenium/location_strategy_javascript/label.js +16 -0
- data/lib/webrat/selenium/location_strategy_javascript/webrat.js +5 -0
- data/lib/webrat/selenium/location_strategy_javascript/webratlink.js +9 -0
- data/lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js +15 -0
- data/lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js +5 -0
- data/lib/webrat/selenium/matchers/have_content.rb +66 -0
- data/lib/webrat/selenium/matchers/have_selector.rb +49 -0
- data/lib/webrat/selenium/matchers/have_tag.rb +72 -0
- data/lib/webrat/selenium/matchers/have_xpath.rb +45 -0
- data/lib/webrat/selenium/matchers.rb +4 -0
- data/lib/webrat/selenium/merb_application_server.rb +48 -0
- data/lib/webrat/selenium/rails_application_server.rb +42 -0
- data/lib/webrat/selenium/selenium_extensions.js +6 -0
- data/lib/webrat/selenium/selenium_rc_server.rb +80 -0
- data/lib/webrat/selenium/selenium_session.rb +241 -0
- data/lib/webrat/selenium/sinatra_application_server.rb +35 -0
- data/lib/webrat/selenium.rb +80 -0
- data/lib/webrat/sinatra.rb +44 -0
- data/lib/webrat.rb +34 -0
- data/vendor/selenium-server.jar +0 -0
- metadata +147 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
require "mechanize"
|
2
|
+
|
3
|
+
module Webrat #:nodoc:
|
4
|
+
class MechanizeSession < Session #:nodoc:
|
5
|
+
|
6
|
+
attr_accessor :response
|
7
|
+
alias :page :response
|
8
|
+
|
9
|
+
def request_page(url, http_method, data) #:nodoc:
|
10
|
+
super(absolute_url(url), http_method, data)
|
11
|
+
end
|
12
|
+
|
13
|
+
def get(url, data, headers_argument_not_used = nil)
|
14
|
+
@response = mechanize.get(url, data)
|
15
|
+
end
|
16
|
+
|
17
|
+
def post(url, data, headers_argument_not_used = nil)
|
18
|
+
post_data = data.inject({}) do |memo, param|
|
19
|
+
case param.last
|
20
|
+
when Hash
|
21
|
+
param.last.each {|attribute, value| memo["#{param.first}[#{attribute}]"] = value }
|
22
|
+
else
|
23
|
+
memo[param.first] = param.last
|
24
|
+
end
|
25
|
+
memo
|
26
|
+
end
|
27
|
+
@response = mechanize.post(url, post_data)
|
28
|
+
end
|
29
|
+
|
30
|
+
def response_body
|
31
|
+
@response.content
|
32
|
+
end
|
33
|
+
|
34
|
+
def response_code
|
35
|
+
@response.code.to_i
|
36
|
+
end
|
37
|
+
|
38
|
+
def mechanize
|
39
|
+
@mechanize ||= WWW::Mechanize.new
|
40
|
+
end
|
41
|
+
|
42
|
+
def_delegators :mechanize, :basic_auth
|
43
|
+
|
44
|
+
def absolute_url(url) #:nodoc:
|
45
|
+
current_host, current_path = split_current_url
|
46
|
+
if url =~ Regexp.new('^https?://')
|
47
|
+
url
|
48
|
+
elsif url =~ Regexp.new('^/')
|
49
|
+
current_host + url
|
50
|
+
elsif url =~ Regexp.new('^\.')
|
51
|
+
current_host + absolute_path(current_path, url)
|
52
|
+
else
|
53
|
+
url
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def split_current_url
|
59
|
+
current_url =~ Regexp.new('^(https?://[^/]+)(/.*)?')
|
60
|
+
[Regexp.last_match(1), Regexp.last_match(2)]
|
61
|
+
end
|
62
|
+
|
63
|
+
def absolute_path(current_path, url)
|
64
|
+
levels_up = url.split('/').find_all { |x| x == '..' }.size
|
65
|
+
ancestor = if current_path.nil?
|
66
|
+
""
|
67
|
+
else
|
68
|
+
current_path.split("/")[0..(-1 - levels_up)].join("/")
|
69
|
+
end
|
70
|
+
descendent = url.split("/")[levels_up..-1]
|
71
|
+
"#{ancestor}/#{descendent}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/webrat/merb.rb
ADDED
@@ -0,0 +1,65 @@
|
|
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
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
module Merb #:nodoc:
|
51
|
+
module Test #:nodoc:
|
52
|
+
module RequestHelper #:nodoc:
|
53
|
+
def request(uri, env = {})
|
54
|
+
@_webrat_session ||= Webrat::MerbSession.new
|
55
|
+
@_webrat_session.response = @_webrat_session.request(uri, env)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class Merb::Test::RspecStory #:nodoc:
|
62
|
+
def browser
|
63
|
+
@browser ||= Webrat::MerbSession.new
|
64
|
+
end
|
65
|
+
end
|
data/lib/webrat/rack.rb
ADDED
@@ -0,0 +1,24 @@
|
|
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
|
data/lib/webrat/rails.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require "webrat"
|
2
|
+
|
3
|
+
require "action_controller"
|
4
|
+
require "action_controller/integration"
|
5
|
+
require "action_controller/record_identifier"
|
6
|
+
|
7
|
+
module Webrat
|
8
|
+
class RailsSession < Session #:nodoc:
|
9
|
+
include ActionController::RecordIdentifier
|
10
|
+
|
11
|
+
# The Rails version of within supports passing in a model and Webrat
|
12
|
+
# will apply a scope based on Rails' dom_id for that model.
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
# within User.last do
|
16
|
+
# click_link "Delete"
|
17
|
+
# end
|
18
|
+
def within(selector_or_object, &block)
|
19
|
+
if selector_or_object.is_a?(String)
|
20
|
+
super
|
21
|
+
else
|
22
|
+
super('#' + dom_id(selector_or_object), &block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def doc_root
|
27
|
+
File.expand_path(File.join(RAILS_ROOT, 'public'))
|
28
|
+
end
|
29
|
+
|
30
|
+
def saved_page_dir
|
31
|
+
File.expand_path(File.join(RAILS_ROOT, "tmp"))
|
32
|
+
end
|
33
|
+
|
34
|
+
def get(url, data, headers = nil)
|
35
|
+
do_request(:get, url, data, headers)
|
36
|
+
end
|
37
|
+
|
38
|
+
def post(url, data, headers = nil)
|
39
|
+
do_request(:post, url, data, headers)
|
40
|
+
end
|
41
|
+
|
42
|
+
def put(url, data, headers = nil)
|
43
|
+
do_request(:put, url, data, headers)
|
44
|
+
end
|
45
|
+
|
46
|
+
def delete(url, data, headers = nil)
|
47
|
+
do_request(:delete, url, data, headers)
|
48
|
+
end
|
49
|
+
|
50
|
+
def response_body
|
51
|
+
response.body
|
52
|
+
end
|
53
|
+
|
54
|
+
def response_code
|
55
|
+
response.code.to_i
|
56
|
+
end
|
57
|
+
|
58
|
+
def xml_content_type?
|
59
|
+
response.headers["Content-Type"].to_s =~ /xml/
|
60
|
+
end
|
61
|
+
|
62
|
+
protected
|
63
|
+
|
64
|
+
def integration_session
|
65
|
+
@context
|
66
|
+
end
|
67
|
+
|
68
|
+
def do_request(http_method, url, data, headers) #:nodoc:
|
69
|
+
update_protocol(url)
|
70
|
+
integration_session.send(http_method, normalize_url(url), data, headers)
|
71
|
+
end
|
72
|
+
|
73
|
+
# remove protocol, host and anchor
|
74
|
+
def normalize_url(href) #:nodoc:
|
75
|
+
uri = URI.parse(href)
|
76
|
+
normalized_url = []
|
77
|
+
normalized_url << "#{uri.scheme}://" if uri.scheme
|
78
|
+
normalized_url << uri.host if uri.host
|
79
|
+
normalized_url << ":#{uri.port}" if uri.port && ![80,443].include?(uri.port)
|
80
|
+
normalized_url << uri.path if uri.path
|
81
|
+
normalized_url << "?#{uri.query}" if uri.query
|
82
|
+
normalized_url.join
|
83
|
+
end
|
84
|
+
|
85
|
+
def update_protocol(href) #:nodoc:
|
86
|
+
if href =~ /^https:/
|
87
|
+
integration_session.https!(true)
|
88
|
+
elsif href =~ /^http:/
|
89
|
+
integration_session.https!(false)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def response #:nodoc:
|
94
|
+
integration_session.response
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
module ActionController #:nodoc:
|
101
|
+
IntegrationTest.class_eval do
|
102
|
+
include Webrat::Methods
|
103
|
+
include Webrat::Matchers
|
104
|
+
end
|
105
|
+
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,71 @@
|
|
1
|
+
module Webrat
|
2
|
+
module Selenium
|
3
|
+
|
4
|
+
class ApplicationServer
|
5
|
+
|
6
|
+
def self.boot
|
7
|
+
case Webrat.configuration.application_framework
|
8
|
+
when :sinatra
|
9
|
+
require "webrat/selenium/sinatra_application_server"
|
10
|
+
SinatraApplicationServer.new.boot
|
11
|
+
when :merb
|
12
|
+
require "webrat/selenium/merb_application_server"
|
13
|
+
MerbApplicationServer.new.boot
|
14
|
+
when :rails
|
15
|
+
require "webrat/selenium/rails_application_server"
|
16
|
+
RailsApplicationServer.new.boot
|
17
|
+
else
|
18
|
+
raise WebratError.new(<<-STR)
|
19
|
+
Unknown Webrat application_framework: #{Webrat.configuration.application_framework.inspect}
|
20
|
+
|
21
|
+
Please ensure you have a Webrat configuration block that specifies an application_framework
|
22
|
+
in your test_helper.rb, spec_helper.rb, or env.rb (for Cucumber).
|
23
|
+
|
24
|
+
For example:
|
25
|
+
|
26
|
+
Webrat.configure do |config|
|
27
|
+
# ...
|
28
|
+
config.application_framework = :rails
|
29
|
+
end
|
30
|
+
STR
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def boot
|
35
|
+
start
|
36
|
+
wait
|
37
|
+
stop_at_exit
|
38
|
+
end
|
39
|
+
|
40
|
+
def stop_at_exit
|
41
|
+
at_exit do
|
42
|
+
stop
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def wait
|
47
|
+
$stderr.print "==> Waiting for #{Webrat.configuration.application_framework} application server on port #{Webrat.configuration.application_port}... "
|
48
|
+
wait_for_socket
|
49
|
+
$stderr.print "Ready!\n"
|
50
|
+
end
|
51
|
+
|
52
|
+
def wait_for_socket
|
53
|
+
silence_stream(STDOUT) do
|
54
|
+
TCPSocket.wait_for_service_with_timeout \
|
55
|
+
:host => Webrat.configuration.application_address,
|
56
|
+
:port => Webrat.configuration.application_port.to_i,
|
57
|
+
:timeout => 30 # seconds
|
58
|
+
end
|
59
|
+
rescue SocketError
|
60
|
+
fail
|
61
|
+
end
|
62
|
+
|
63
|
+
def prepare_pid_file(file_path, pid_file_name)
|
64
|
+
FileUtils.mkdir_p File.expand_path(file_path)
|
65
|
+
File.expand_path("#{file_path}/#{pid_file_name}")
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
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,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
|