benschwarz-webrat 0.3.2.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.
- data/History.txt +184 -0
- data/MIT-LICENSE.txt +19 -0
- data/README.rdoc +81 -0
- data/Rakefile +104 -0
- data/install.rb +1 -0
- data/lib/webrat.rb +34 -0
- data/lib/webrat/core.rb +13 -0
- data/lib/webrat/core/configuration.rb +44 -0
- data/lib/webrat/core/elements/area.rb +31 -0
- data/lib/webrat/core/elements/element.rb +29 -0
- data/lib/webrat/core/elements/field.rb +386 -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 +94 -0
- data/lib/webrat/core/elements/select_option.rb +35 -0
- data/lib/webrat/core/locators.rb +20 -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 +50 -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/logging.rb +21 -0
- data/lib/webrat/core/matchers.rb +4 -0
- data/lib/webrat/core/matchers/have_content.rb +55 -0
- data/lib/webrat/core/matchers/have_selector.rb +37 -0
- data/lib/webrat/core/matchers/have_tag.rb +57 -0
- data/lib/webrat/core/matchers/have_xpath.rb +83 -0
- data/lib/webrat/core/methods.rb +54 -0
- data/lib/webrat/core/mime.rb +29 -0
- data/lib/webrat/core/scope.rb +318 -0
- data/lib/webrat/core/session.rb +241 -0
- data/lib/webrat/core/xml.rb +99 -0
- data/lib/webrat/core/xml/hpricot.rb +19 -0
- data/lib/webrat/core/xml/nokogiri.rb +44 -0
- data/lib/webrat/core/xml/rexml.rb +24 -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/hash_with_indifferent_access.rb +131 -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/mechanize.rb +43 -0
- data/lib/webrat/merb.rb +77 -0
- data/lib/webrat/rack.rb +26 -0
- data/lib/webrat/rails.rb +88 -0
- data/lib/webrat/rails/redirect_actions.rb +18 -0
- data/lib/webrat/rspec-rails.rb +13 -0
- data/lib/webrat/selenium.rb +58 -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/selenium_extensions.js +6 -0
- data/lib/webrat/selenium/selenium_session.rb +186 -0
- data/lib/webrat/sinatra.rb +21 -0
- data/vendor/selenium-server.jar +0 -0
- metadata +144 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
require "webrat/core/xml/nokogiri"
|
2
|
+
require "webrat/core/xml/hpricot"
|
3
|
+
require "webrat/core/xml/rexml"
|
4
|
+
|
5
|
+
module Webrat #:nodoc:
|
6
|
+
module XML #:nodoc:
|
7
|
+
|
8
|
+
def self.document(stringlike) #:nodoc:
|
9
|
+
if Webrat.configuration.parse_with_nokogiri?
|
10
|
+
Webrat.nokogiri_document(stringlike)
|
11
|
+
else
|
12
|
+
Webrat.rexml_document(Webrat.hpricot_document(stringlike).to_html)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.to_html(element)
|
17
|
+
if Webrat.configuration.parse_with_nokogiri?
|
18
|
+
element.to_html
|
19
|
+
else
|
20
|
+
element.to_s
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.inner_html(element)
|
25
|
+
if Webrat.configuration.parse_with_nokogiri?
|
26
|
+
element.inner_html
|
27
|
+
else
|
28
|
+
element.text
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.all_inner_text(element)
|
33
|
+
if Webrat.configuration.parse_with_nokogiri?
|
34
|
+
element.inner_text
|
35
|
+
else
|
36
|
+
Hpricot(element.to_s).children.first.inner_text
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.inner_text(element)
|
41
|
+
if Webrat.configuration.parse_with_nokogiri?
|
42
|
+
element.inner_text
|
43
|
+
else
|
44
|
+
if defined?(Hpricot::Doc) && element.is_a?(Hpricot::Doc)
|
45
|
+
element.inner_text
|
46
|
+
else
|
47
|
+
element.text
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.xpath_to(element)
|
53
|
+
if Webrat.configuration.parse_with_nokogiri?
|
54
|
+
element.path
|
55
|
+
else
|
56
|
+
element.xpath
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.attribute(element, attribute_name)
|
61
|
+
return element[attribute_name] if element.is_a?(Hash)
|
62
|
+
|
63
|
+
if Webrat.configuration.parse_with_nokogiri?
|
64
|
+
element[attribute_name]
|
65
|
+
else
|
66
|
+
element.attributes[attribute_name]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.xpath_at(*args)
|
71
|
+
xpath_search(*args).first
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.css_at(*args)
|
75
|
+
css_search(*args).first
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.xpath_search(element, *searches)
|
79
|
+
searches.flatten.map do |search|
|
80
|
+
if Webrat.configuration.parse_with_nokogiri?
|
81
|
+
element.xpath(search)
|
82
|
+
else
|
83
|
+
REXML::XPath.match(element, search)
|
84
|
+
end
|
85
|
+
end.flatten.compact
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.css_search(element, *searches) #:nodoc:
|
89
|
+
xpath_search(element, css_to_xpath(*searches))
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.css_to_xpath(*selectors)
|
93
|
+
selectors.map do |rule|
|
94
|
+
Nokogiri::CSS.xpath_for(rule, :prefix => ".//")
|
95
|
+
end.flatten.uniq
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Webrat
|
2
|
+
|
3
|
+
def self.hpricot_document(stringlike)
|
4
|
+
return stringlike.dom if stringlike.respond_to?(:dom)
|
5
|
+
|
6
|
+
if Hpricot::Doc === stringlike
|
7
|
+
stringlike
|
8
|
+
elsif Hpricot::Elements === stringlike
|
9
|
+
stringlike
|
10
|
+
elsif StringIO === stringlike
|
11
|
+
Hpricot(stringlike.string)
|
12
|
+
elsif stringlike.respond_to?(:body)
|
13
|
+
Hpricot(stringlike.body.to_s)
|
14
|
+
else
|
15
|
+
Hpricot(stringlike.to_s)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "webrat/core_extensions/meta_class"
|
2
|
+
|
3
|
+
module Webrat
|
4
|
+
|
5
|
+
def self.nokogiri_document(stringlike) #:nodoc:
|
6
|
+
return stringlike.dom if stringlike.respond_to?(:dom)
|
7
|
+
|
8
|
+
if Nokogiri::HTML::Document === stringlike
|
9
|
+
stringlike
|
10
|
+
elsif Nokogiri::XML::NodeSet === stringlike
|
11
|
+
stringlike
|
12
|
+
elsif StringIO === stringlike
|
13
|
+
Nokogiri.parse(stringlike.string)
|
14
|
+
elsif stringlike.respond_to?(:body)
|
15
|
+
Nokogiri.parse(stringlike.body.to_s)
|
16
|
+
else
|
17
|
+
Nokogiri.parse(stringlike.to_s)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.define_dom_method(object, dom) #:nodoc:
|
22
|
+
object.meta_class.send(:define_method, :dom) do
|
23
|
+
dom
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
module Nokogiri #:nodoc:
|
31
|
+
module CSS #:nodoc:
|
32
|
+
class XPathVisitor #:nodoc:
|
33
|
+
|
34
|
+
def visit_pseudo_class_text(node) #:nodoc:
|
35
|
+
"@type='text'"
|
36
|
+
end
|
37
|
+
|
38
|
+
def visit_pseudo_class_password(node) #:nodoc:
|
39
|
+
"@type='password'"
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Webrat
|
2
|
+
|
3
|
+
def self.rexml_document(stringlike)
|
4
|
+
stringlike = stringlike.body.to_s if stringlike.respond_to?(:body)
|
5
|
+
|
6
|
+
case stringlike
|
7
|
+
when REXML::Document
|
8
|
+
stringlike.root
|
9
|
+
when REXML::Node, Array
|
10
|
+
stringlike
|
11
|
+
else
|
12
|
+
begin
|
13
|
+
REXML::Document.new(stringlike.to_s).root
|
14
|
+
rescue REXML::ParseException => e
|
15
|
+
if e.message.include?("second root element")
|
16
|
+
REXML::Document.new("<fake-root-element>#{stringlike}</fake-root-element>").root
|
17
|
+
else
|
18
|
+
raise e
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class Object #:nodoc:
|
2
|
+
# An object is blank if it's false, empty, or a whitespace string.
|
3
|
+
# For example, "", " ", +nil+, [], and {} are blank.
|
4
|
+
#
|
5
|
+
# This simplifies
|
6
|
+
#
|
7
|
+
# if !address.nil? && !address.empty?
|
8
|
+
#
|
9
|
+
# to
|
10
|
+
#
|
11
|
+
# if !address.blank?
|
12
|
+
def blank?
|
13
|
+
respond_to?(:empty?) ? empty? : !self
|
14
|
+
end
|
15
|
+
|
16
|
+
# An object is present if it's not blank.
|
17
|
+
def present?
|
18
|
+
!blank?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class NilClass #:nodoc:
|
23
|
+
def blank?
|
24
|
+
true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class FalseClass #:nodoc:
|
29
|
+
def blank?
|
30
|
+
true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class TrueClass #:nodoc:
|
35
|
+
def blank?
|
36
|
+
false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Array #:nodoc:
|
41
|
+
alias_method :blank?, :empty?
|
42
|
+
end
|
43
|
+
|
44
|
+
class Hash #:nodoc:
|
45
|
+
alias_method :blank?, :empty?
|
46
|
+
end
|
47
|
+
|
48
|
+
class String #:nodoc:
|
49
|
+
def blank?
|
50
|
+
self !~ /\S/
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Numeric #:nodoc:
|
55
|
+
def blank?
|
56
|
+
false
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# This class has dubious semantics and we only have it so that
|
2
|
+
# people can write params[:key] instead of params['key']
|
3
|
+
# and they get the same value for both keys.
|
4
|
+
class HashWithIndifferentAccess < Hash #:nodoc:
|
5
|
+
def initialize(constructor = {})
|
6
|
+
if constructor.is_a?(Hash)
|
7
|
+
super()
|
8
|
+
update(constructor)
|
9
|
+
else
|
10
|
+
super(constructor)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def default(key = nil)
|
15
|
+
if key.is_a?(Symbol) && include?(key = key.to_s)
|
16
|
+
self[key]
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
|
23
|
+
alias_method :regular_update, :update unless method_defined?(:regular_update)
|
24
|
+
|
25
|
+
#
|
26
|
+
# Assigns a new value to the hash.
|
27
|
+
#
|
28
|
+
# Example:
|
29
|
+
#
|
30
|
+
# hash = HashWithIndifferentAccess.new
|
31
|
+
# hash[:key] = "value"
|
32
|
+
#
|
33
|
+
def []=(key, value)
|
34
|
+
regular_writer(convert_key(key), convert_value(value))
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# Updates the instantized hash with values from the second.
|
39
|
+
#
|
40
|
+
# Example:
|
41
|
+
#
|
42
|
+
# >> hash_1 = HashWithIndifferentAccess.new
|
43
|
+
# => {}
|
44
|
+
#
|
45
|
+
# >> hash_1[:key] = "value"
|
46
|
+
# => "value"
|
47
|
+
#
|
48
|
+
# >> hash_2 = HashWithIndifferentAccess.new
|
49
|
+
# => {}
|
50
|
+
#
|
51
|
+
# >> hash_2[:key] = "New Value!"
|
52
|
+
# => "New Value!"
|
53
|
+
#
|
54
|
+
# >> hash_1.update(hash_2)
|
55
|
+
# => {"key"=>"New Value!"}
|
56
|
+
#
|
57
|
+
def update(other_hash)
|
58
|
+
other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
alias_method :merge!, :update
|
63
|
+
|
64
|
+
# Checks the hash for a key matching the argument passed in
|
65
|
+
def key?(key)
|
66
|
+
super(convert_key(key))
|
67
|
+
end
|
68
|
+
|
69
|
+
alias_method :include?, :key?
|
70
|
+
alias_method :has_key?, :key?
|
71
|
+
alias_method :member?, :key?
|
72
|
+
|
73
|
+
# Fetches the value for the specified key, same as doing hash[key]
|
74
|
+
def fetch(key, *extras)
|
75
|
+
super(convert_key(key), *extras)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns an array of the values at the specified indicies.
|
79
|
+
def values_at(*indices)
|
80
|
+
indices.collect {|key| self[convert_key(key)]}
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns an exact copy of the hash.
|
84
|
+
def dup
|
85
|
+
HashWithIndifferentAccess.new(self)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Merges the instantized and the specified hashes together, giving precedence to the values from the second hash
|
89
|
+
# Does not overwrite the existing hash.
|
90
|
+
def merge(hash)
|
91
|
+
self.dup.update(hash)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Removes a specified key from the hash.
|
95
|
+
def delete(key)
|
96
|
+
super(convert_key(key))
|
97
|
+
end
|
98
|
+
|
99
|
+
def stringify_keys!; self end
|
100
|
+
def symbolize_keys!; self end
|
101
|
+
def to_options!; self end
|
102
|
+
|
103
|
+
# Convert to a Hash with String keys.
|
104
|
+
def to_hash
|
105
|
+
Hash.new(default).merge(self)
|
106
|
+
end
|
107
|
+
|
108
|
+
protected
|
109
|
+
def convert_key(key)
|
110
|
+
key.kind_of?(Symbol) ? key.to_s : key
|
111
|
+
end
|
112
|
+
|
113
|
+
def convert_value(value)
|
114
|
+
case value
|
115
|
+
when Hash
|
116
|
+
value.with_indifferent_access
|
117
|
+
when Array
|
118
|
+
value.collect { |e| e.is_a?(Hash) ? e.with_indifferent_access : e }
|
119
|
+
else
|
120
|
+
value
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
class Hash #:nodoc:
|
126
|
+
def with_indifferent_access
|
127
|
+
hash = HashWithIndifferentAccess.new(self)
|
128
|
+
hash.default = self.default
|
129
|
+
hash
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,43 @@
|
|
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 get(url, data, headers_argument_not_used = nil)
|
10
|
+
@response = mechanize.get(url, data)
|
11
|
+
end
|
12
|
+
|
13
|
+
def post(url, data, headers_argument_not_used = nil)
|
14
|
+
post_data = data.inject({}) do |memo, param|
|
15
|
+
case param.last
|
16
|
+
when Hash
|
17
|
+
param.last.each {|attribute, value| memo["#{param.first}[#{attribute}]"] = value }
|
18
|
+
else
|
19
|
+
memo[param.first] = param.last
|
20
|
+
end
|
21
|
+
memo
|
22
|
+
end
|
23
|
+
@response = mechanize.post(url, post_data)
|
24
|
+
end
|
25
|
+
|
26
|
+
def response_body
|
27
|
+
@response.content
|
28
|
+
end
|
29
|
+
|
30
|
+
def response_code
|
31
|
+
@response.code.to_i
|
32
|
+
end
|
33
|
+
|
34
|
+
def mechanize
|
35
|
+
@mechanize = WWW::Mechanize.new
|
36
|
+
end
|
37
|
+
|
38
|
+
def_delegators :mechanize, :basic_auth
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Webrat.configuration.mode = :mechanize
|