mkuklis-webrat 0.5.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/.document +4 -0
- data/.gitignore +15 -0
- data/History.txt +413 -0
- data/MIT-LICENSE.txt +19 -0
- data/README.rdoc +85 -0
- data/Rakefile +188 -0
- data/VERSION +1 -0
- data/install.rb +1 -0
- data/lib/webrat/adapters/mechanize.rb +78 -0
- data/lib/webrat/adapters/merb.rb +11 -0
- data/lib/webrat/adapters/rack.rb +25 -0
- data/lib/webrat/adapters/rails.rb +81 -0
- data/lib/webrat/adapters/sinatra.rb +9 -0
- data/lib/webrat/core/configuration.rb +92 -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 +487 -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 +93 -0
- data/lib/webrat/core/elements/select_option.rb +48 -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 +74 -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 +23 -0
- data/lib/webrat/core/matchers/have_content.rb +68 -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 +122 -0
- data/lib/webrat/core/matchers.rb +4 -0
- data/lib/webrat/core/methods.rb +64 -0
- data/lib/webrat/core/mime.rb +18 -0
- data/lib/webrat/core/save_and_open_page.rb +48 -0
- data/lib/webrat/core/scope.rb +365 -0
- data/lib/webrat/core/session.rb +306 -0
- data/lib/webrat/core/xml.rb +72 -0
- data/lib/webrat/core.rb +13 -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/integrations/merb.rb +10 -0
- data/lib/webrat/integrations/rails.rb +25 -0
- data/lib/webrat/integrations/rspec-rails.rb +10 -0
- data/lib/webrat/integrations/selenium.rb +11 -0
- data/lib/webrat/merb.rb +9 -0
- data/lib/webrat/rspec-rails.rb +2 -0
- data/lib/webrat/selenium/application_server_factory.rb +40 -0
- data/lib/webrat/selenium/application_servers/base.rb +54 -0
- data/lib/webrat/selenium/application_servers/external.rb +26 -0
- data/lib/webrat/selenium/application_servers/merb.rb +50 -0
- data/lib/webrat/selenium/application_servers/rails.rb +67 -0
- data/lib/webrat/selenium/application_servers/sinatra.rb +37 -0
- data/lib/webrat/selenium/application_servers.rb +5 -0
- data/lib/webrat/selenium/location_strategy_javascript/button.js +19 -0
- data/lib/webrat/selenium/location_strategy_javascript/label.js +42 -0
- data/lib/webrat/selenium/location_strategy_javascript/webrat.js +6 -0
- data/lib/webrat/selenium/location_strategy_javascript/webratlink.js +32 -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/selenium_extensions.js +6 -0
- data/lib/webrat/selenium/selenium_rc_server.rb +86 -0
- data/lib/webrat/selenium/selenium_session.rb +272 -0
- data/lib/webrat/selenium/silence_stream.rb +18 -0
- data/lib/webrat/selenium.rb +70 -0
- data/lib/webrat.rb +18 -0
- data/spec/fakes/test_adapter.rb +37 -0
- data/spec/integration/mechanize/Rakefile +7 -0
- data/spec/integration/mechanize/config.ru +2 -0
- data/spec/integration/mechanize/sample_app.rb +20 -0
- data/spec/integration/mechanize/spec/mechanize_spec.rb +22 -0
- data/spec/integration/mechanize/spec/spec_helper.rb +27 -0
- data/spec/integration/merb/.gitignore +21 -0
- data/spec/integration/merb/Rakefile +35 -0
- data/spec/integration/merb/app/controllers/application.rb +2 -0
- data/spec/integration/merb/app/controllers/exceptions.rb +13 -0
- data/spec/integration/merb/app/controllers/testing.rb +27 -0
- data/spec/integration/merb/app/views/exceptions/not_acceptable.html.erb +63 -0
- data/spec/integration/merb/app/views/exceptions/not_found.html.erb +47 -0
- data/spec/integration/merb/app/views/layout/application.html.erb +12 -0
- data/spec/integration/merb/app/views/testing/show_form.html.erb +27 -0
- data/spec/integration/merb/app/views/testing/upload.html.erb +9 -0
- data/spec/integration/merb/config/environments/development.rb +15 -0
- data/spec/integration/merb/config/environments/rake.rb +11 -0
- data/spec/integration/merb/config/environments/test.rb +14 -0
- data/spec/integration/merb/config/init.rb +25 -0
- data/spec/integration/merb/config/rack.rb +11 -0
- data/spec/integration/merb/config/router.rb +34 -0
- data/spec/integration/merb/spec/spec.opts +1 -0
- data/spec/integration/merb/spec/spec_helper.rb +26 -0
- data/spec/integration/merb/spec/webrat_spec.rb +39 -0
- data/spec/integration/merb/tasks/merb.thor/app_script.rb +31 -0
- data/spec/integration/merb/tasks/merb.thor/common.rb +64 -0
- data/spec/integration/merb/tasks/merb.thor/gem_ext.rb +124 -0
- data/spec/integration/merb/tasks/merb.thor/main.thor +150 -0
- data/spec/integration/merb/tasks/merb.thor/ops.rb +93 -0
- data/spec/integration/merb/tasks/merb.thor/utils.rb +40 -0
- data/spec/integration/rack/Rakefile +5 -0
- data/spec/integration/rack/app.rb +89 -0
- data/spec/integration/rack/test/helper.rb +21 -0
- data/spec/integration/rack/test/webrat_rack_test.rb +73 -0
- data/spec/integration/rails/.gitignore +3 -0
- data/spec/integration/rails/Rakefile +30 -0
- data/spec/integration/rails/app/controllers/application.rb +15 -0
- data/spec/integration/rails/app/controllers/buttons_controller.rb +7 -0
- data/spec/integration/rails/app/controllers/fields_controller.rb +4 -0
- data/spec/integration/rails/app/controllers/links_controller.rb +7 -0
- data/spec/integration/rails/app/controllers/webrat_controller.rb +46 -0
- data/spec/integration/rails/app/helpers/buttons_helper.rb +2 -0
- data/spec/integration/rails/app/helpers/fields_helper.rb +2 -0
- data/spec/integration/rails/app/helpers/links_helper.rb +2 -0
- data/spec/integration/rails/app/views/buttons/show.html.erb +11 -0
- data/spec/integration/rails/app/views/fields/show.html.erb +9 -0
- data/spec/integration/rails/app/views/links/show.html.erb +5 -0
- data/spec/integration/rails/app/views/webrat/before_redirect_form.html.erb +4 -0
- data/spec/integration/rails/app/views/webrat/buttons.html.erb +11 -0
- data/spec/integration/rails/app/views/webrat/form.html.erb +28 -0
- data/spec/integration/rails/app/views/webrat/within.html.erb +3 -0
- data/spec/integration/rails/config/boot.rb +109 -0
- data/spec/integration/rails/config/environment.rb +12 -0
- data/spec/integration/rails/config/environments/development.rb +17 -0
- data/spec/integration/rails/config/environments/selenium.rb +22 -0
- data/spec/integration/rails/config/environments/test.rb +22 -0
- data/spec/integration/rails/config/initializers/inflections.rb +10 -0
- data/spec/integration/rails/config/initializers/mime_types.rb +5 -0
- data/spec/integration/rails/config/initializers/new_rails_defaults.rb +17 -0
- data/spec/integration/rails/config/locales/en.yml +5 -0
- data/spec/integration/rails/config/routes.rb +19 -0
- data/spec/integration/rails/public/404.html +30 -0
- data/spec/integration/rails/public/422.html +30 -0
- data/spec/integration/rails/public/500.html +33 -0
- data/spec/integration/rails/script/about +4 -0
- data/spec/integration/rails/script/console +3 -0
- data/spec/integration/rails/script/dbconsole +3 -0
- data/spec/integration/rails/script/destroy +3 -0
- data/spec/integration/rails/script/generate +3 -0
- data/spec/integration/rails/script/performance/benchmarker +3 -0
- data/spec/integration/rails/script/performance/profiler +3 -0
- data/spec/integration/rails/script/performance/request +3 -0
- data/spec/integration/rails/script/plugin +3 -0
- data/spec/integration/rails/script/process/inspector +3 -0
- data/spec/integration/rails/script/process/reaper +3 -0
- data/spec/integration/rails/script/process/spawner +3 -0
- data/spec/integration/rails/script/runner +3 -0
- data/spec/integration/rails/script/server +3 -0
- data/spec/integration/rails/test/integration/button_click_test.rb +80 -0
- data/spec/integration/rails/test/integration/fill_in_test.rb +24 -0
- data/spec/integration/rails/test/integration/link_click_test.rb +27 -0
- data/spec/integration/rails/test/integration/webrat_test.rb +122 -0
- data/spec/integration/rails/test/test_helper.rb +26 -0
- data/spec/integration/sinatra/Rakefile +5 -0
- data/spec/integration/sinatra/classic_app.rb +64 -0
- data/spec/integration/sinatra/modular_app.rb +16 -0
- data/spec/integration/sinatra/test/classic_app_test.rb +37 -0
- data/spec/integration/sinatra/test/modular_app_test.rb +18 -0
- data/spec/integration/sinatra/test/test_helper.rb +17 -0
- data/spec/private/core/configuration_spec.rb +87 -0
- data/spec/private/core/field_spec.rb +85 -0
- data/spec/private/core/link_spec.rb +24 -0
- data/spec/private/core/session_spec.rb +200 -0
- data/spec/private/mechanize/mechanize_adapter_spec.rb +73 -0
- data/spec/private/nokogiri_spec.rb +77 -0
- data/spec/private/rails/attaches_file_spec.rb +81 -0
- data/spec/private/rails/rails_adapter_spec.rb +86 -0
- data/spec/private/selenium/application_servers/rails_spec.rb +26 -0
- data/spec/public/basic_auth_spec.rb +24 -0
- data/spec/public/check_spec.rb +191 -0
- data/spec/public/choose_spec.rb +118 -0
- data/spec/public/click_area_spec.rb +106 -0
- data/spec/public/click_button_spec.rb +494 -0
- data/spec/public/click_link_spec.rb +511 -0
- data/spec/public/fill_in_spec.rb +224 -0
- data/spec/public/locators/field_by_xpath_spec.rb +19 -0
- data/spec/public/locators/field_labeled_spec.rb +172 -0
- data/spec/public/locators/field_with_id_spec.rb +16 -0
- data/spec/public/matchers/contain_spec.rb +114 -0
- data/spec/public/matchers/have_selector_spec.rb +146 -0
- data/spec/public/matchers/have_tag_spec.rb +39 -0
- data/spec/public/matchers/have_xpath_spec.rb +136 -0
- data/spec/public/reload_spec.rb +10 -0
- data/spec/public/save_and_open_spec.rb +70 -0
- data/spec/public/select_date_spec.rb +112 -0
- data/spec/public/select_datetime_spec.rb +137 -0
- data/spec/public/select_spec.rb +455 -0
- data/spec/public/select_time_spec.rb +100 -0
- data/spec/public/selenium/application_server_factory_spec.rb +49 -0
- data/spec/public/selenium/application_servers/external_spec.rb +12 -0
- data/spec/public/selenium/selenium_session_spec.rb +37 -0
- data/spec/public/set_hidden_field_spec.rb +5 -0
- data/spec/public/submit_form_spec.rb +5 -0
- data/spec/public/visit_spec.rb +58 -0
- data/spec/public/within_spec.rb +177 -0
- data/spec/rcov.opts +1 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +54 -0
- data/vendor/selenium-server.jar +0 -0
- metadata +409 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
require "webrat/core/matchers/have_selector"
|
2
|
+
|
3
|
+
module Webrat
|
4
|
+
module HaveTagMatcher
|
5
|
+
|
6
|
+
def have_tag(*args, &block)
|
7
|
+
have_selector(*args, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
alias_method :match_tag, :have_tag
|
11
|
+
|
12
|
+
def assert_have_tag(*args, &block)
|
13
|
+
assert_have_selector(*args, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def assert_have_no_tag(*args, &block)
|
17
|
+
assert_have_no_selector(*args, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require "webrat/core/xml"
|
2
|
+
|
3
|
+
module Webrat
|
4
|
+
module Matchers
|
5
|
+
|
6
|
+
class HaveXpath #:nodoc:
|
7
|
+
def initialize(expected, options = {}, &block)
|
8
|
+
@expected = expected
|
9
|
+
@options = options
|
10
|
+
@block = block
|
11
|
+
end
|
12
|
+
|
13
|
+
def matches?(stringlike, &block)
|
14
|
+
@block ||= block
|
15
|
+
matched = matches(stringlike)
|
16
|
+
|
17
|
+
if @options[:count]
|
18
|
+
matched.size == @options[:count].to_i && (!@block || @block.call(matched))
|
19
|
+
else
|
20
|
+
matched.any? && (!@block || @block.call(matched))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def matches(stringlike)
|
25
|
+
nokogiri_matches(stringlike)
|
26
|
+
end
|
27
|
+
|
28
|
+
def nokogiri_matches(stringlike)
|
29
|
+
if Nokogiri::XML::NodeSet === stringlike
|
30
|
+
@query = query.gsub(%r'^//', './/')
|
31
|
+
else
|
32
|
+
@query = query
|
33
|
+
end
|
34
|
+
|
35
|
+
add_options_conditions_to(@query)
|
36
|
+
|
37
|
+
@document = Webrat::XML.document(stringlike)
|
38
|
+
@document.xpath(*@query)
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_options_conditions_to(query)
|
42
|
+
add_attributes_conditions_to(query)
|
43
|
+
add_content_condition_to(query)
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_attributes_conditions_to(query)
|
47
|
+
attribute_conditions = []
|
48
|
+
|
49
|
+
@options.each do |key, value|
|
50
|
+
next if [:content, :count].include?(key)
|
51
|
+
attribute_conditions << "@#{key} = #{xpath_escape(value)}"
|
52
|
+
end
|
53
|
+
|
54
|
+
if attribute_conditions.any?
|
55
|
+
query << "[#{attribute_conditions.join(' and ')}]"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_content_condition_to(query)
|
60
|
+
if @options[:content]
|
61
|
+
query << "[contains(., #{xpath_escape(@options[:content])})]"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def query
|
66
|
+
@expected
|
67
|
+
end
|
68
|
+
|
69
|
+
# ==== Returns
|
70
|
+
# String:: The failure message.
|
71
|
+
def failure_message
|
72
|
+
"expected following text to match xpath #{@expected}:\n#{@document}"
|
73
|
+
end
|
74
|
+
|
75
|
+
# ==== Returns
|
76
|
+
# String:: The failure message to be displayed in negative matches.
|
77
|
+
def negative_failure_message
|
78
|
+
"expected following text to not match xpath #{@expected}:\n#{@document}"
|
79
|
+
end
|
80
|
+
|
81
|
+
protected
|
82
|
+
|
83
|
+
def xpath_escape(string)
|
84
|
+
if string.include?("'") && string.include?('"')
|
85
|
+
parts = string.split("'").map do |part|
|
86
|
+
"'#{part}'"
|
87
|
+
end
|
88
|
+
|
89
|
+
"concat(" + parts.join(", \"'\", ") + ")"
|
90
|
+
elsif string.include?("'")
|
91
|
+
"\"#{string}\""
|
92
|
+
else
|
93
|
+
"'#{string}'"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
# Matches HTML content against an XPath query
|
100
|
+
#
|
101
|
+
# ==== Parameters
|
102
|
+
# expected<String>:: The XPath query to look for.
|
103
|
+
#
|
104
|
+
# ==== Returns
|
105
|
+
# HaveXpath:: A new have xpath matcher.
|
106
|
+
def have_xpath(expected, options = {}, &block)
|
107
|
+
HaveXpath.new(expected, options, &block)
|
108
|
+
end
|
109
|
+
alias_method :match_xpath, :have_xpath
|
110
|
+
|
111
|
+
def assert_have_xpath(expected, options = {}, &block)
|
112
|
+
hs = HaveXpath.new(expected, options, &block)
|
113
|
+
assert hs.matches?(response_body), hs.failure_message
|
114
|
+
end
|
115
|
+
|
116
|
+
def assert_have_no_xpath(expected, options = {}, &block)
|
117
|
+
hs = HaveXpath.new(expected, options, &block)
|
118
|
+
assert !hs.matches?(response_body), hs.negative_failure_message
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Webrat
|
2
|
+
module Methods #:nodoc:
|
3
|
+
|
4
|
+
def self.delegate_to_session(*meths)
|
5
|
+
meths.each do |meth|
|
6
|
+
self.class_eval <<-RUBY
|
7
|
+
def #{meth}(*args, &blk)
|
8
|
+
webrat_session.#{meth}(*args, &blk)
|
9
|
+
end
|
10
|
+
RUBY
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def webrat
|
15
|
+
webrat_session
|
16
|
+
end
|
17
|
+
|
18
|
+
def webrat_session
|
19
|
+
@_webrat_session ||= begin
|
20
|
+
session = Webrat.session_class.new
|
21
|
+
session.adapter = Webrat.adapter_class.new(self) if session.respond_to?(:adapter=)
|
22
|
+
session
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# all of these methods delegate to the @session, which should
|
27
|
+
# be created transparently.
|
28
|
+
#
|
29
|
+
# Note that when using Webrat, #request also uses @session, so
|
30
|
+
# that #request and webrat native functions behave interchangably
|
31
|
+
|
32
|
+
delegate_to_session \
|
33
|
+
:visits, :visit,
|
34
|
+
:within,
|
35
|
+
:header, :http_accept, :basic_auth,
|
36
|
+
:save_and_open_page,
|
37
|
+
:fills_in, :fill_in,
|
38
|
+
:checks, :check,
|
39
|
+
:unchecks, :uncheck,
|
40
|
+
:chooses, :choose,
|
41
|
+
:selects, :select,
|
42
|
+
:unselects, :unselect,
|
43
|
+
:attaches_file, :attach_file,
|
44
|
+
:current_page,
|
45
|
+
:current_url,
|
46
|
+
:clicks_link, :click_link,
|
47
|
+
:clicks_area, :click_area,
|
48
|
+
:clicks_button, :click_button,
|
49
|
+
:reload, :reloads,
|
50
|
+
:clicks_link_within, :click_link_within,
|
51
|
+
:field_labeled,
|
52
|
+
:select_option,
|
53
|
+
:set_hidden_field, :submit_form,
|
54
|
+
:request_page, :current_dom,
|
55
|
+
:response_body,
|
56
|
+
:selects_date, :selects_time, :selects_datetime,
|
57
|
+
:select_date, :select_time, :select_datetime,
|
58
|
+
:field_by_xpath,
|
59
|
+
:field_with_id,
|
60
|
+
:selenium,
|
61
|
+
:simulate, :automate,
|
62
|
+
:field_named
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Webrat #:nodoc:
|
2
|
+
module MIME #:nodoc:
|
3
|
+
MIME_TYPES = Rack::Mime::MIME_TYPES.dup.merge(
|
4
|
+
".multipart_form" => "multipart/form-data",
|
5
|
+
".url_encoded_form" => "application/x-www-form-urlencoded"
|
6
|
+
).freeze
|
7
|
+
|
8
|
+
def mime_type(type)
|
9
|
+
return type if type.nil? || type.to_s.include?("/")
|
10
|
+
type = ".#{type}" unless type.to_s[0] == ?.
|
11
|
+
MIME_TYPES.fetch(type) { |type|
|
12
|
+
raise ArgumentError.new("Invalid Mime type: #{type}")
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
module_function :mime_type
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Webrat
|
2
|
+
module SaveAndOpenPage
|
3
|
+
# Saves the page out to RAILS_ROOT/tmp/ and opens it in the default
|
4
|
+
# web browser if on OS X. Useful for debugging.
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
# save_and_open_page
|
8
|
+
def save_and_open_page
|
9
|
+
return unless File.exist?(saved_page_dir)
|
10
|
+
|
11
|
+
filename = "#{saved_page_dir}/webrat-#{Time.now.to_i}.html"
|
12
|
+
|
13
|
+
File.open(filename, "w") do |f|
|
14
|
+
f.write rewrite_css_and_image_references(response_body)
|
15
|
+
end
|
16
|
+
|
17
|
+
open_in_browser(filename)
|
18
|
+
end
|
19
|
+
|
20
|
+
def open_in_browser(path) # :nodoc
|
21
|
+
require "launchy"
|
22
|
+
Launchy::Browser.run(path)
|
23
|
+
rescue LoadError
|
24
|
+
warn "Sorry, you need to install launchy to open pages: `gem install launchy`"
|
25
|
+
end
|
26
|
+
|
27
|
+
def rewrite_css_and_image_references(response_html) # :nodoc:
|
28
|
+
return response_html unless doc_root
|
29
|
+
response_html.gsub(/("|')\/(stylesheets|images)/, '\1' + doc_root + '/\2')
|
30
|
+
end
|
31
|
+
|
32
|
+
def saved_page_dir #:nodoc:
|
33
|
+
File.expand_path(".")
|
34
|
+
end
|
35
|
+
|
36
|
+
def doc_root #:nodoc:
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# accessor for testing
|
43
|
+
def ruby_platform
|
44
|
+
RUBY_PLATFORM
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,365 @@
|
|
1
|
+
require "webrat/core/elements/form"
|
2
|
+
require "webrat/core/locators"
|
3
|
+
require "webrat/core_extensions/deprecate"
|
4
|
+
|
5
|
+
module Webrat
|
6
|
+
# An HTML element (link, button, field, etc.) that Webrat expected was not found on the page
|
7
|
+
class NotFoundError < WebratError
|
8
|
+
end
|
9
|
+
|
10
|
+
class Scope
|
11
|
+
include Logging
|
12
|
+
include Locators
|
13
|
+
|
14
|
+
def self.from_page(session, response, response_body) #:nodoc:
|
15
|
+
new(session) do
|
16
|
+
@response = response
|
17
|
+
@response_body = response_body
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.from_scope(session, scope, selector) #:nodoc:
|
22
|
+
new(session) do
|
23
|
+
@scope = scope
|
24
|
+
@selector = selector
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_reader :session
|
29
|
+
|
30
|
+
def initialize(session, &block) #:nodoc:
|
31
|
+
@session = session
|
32
|
+
instance_eval(&block) if block_given?
|
33
|
+
|
34
|
+
if @selector && scoped_dom.nil?
|
35
|
+
raise Webrat::NotFoundError.new("The scope was not found on the page: #{@selector.inspect}")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Verifies an input field or textarea exists on the current page, and stores a value for
|
40
|
+
# it which will be sent when the form is submitted.
|
41
|
+
#
|
42
|
+
# Examples:
|
43
|
+
# fill_in "Email", :with => "user@example.com"
|
44
|
+
# fill_in "user[email]", :with => "user@example.com"
|
45
|
+
#
|
46
|
+
# The field value is required, and must be specified in <tt>options[:with]</tt>.
|
47
|
+
# <tt>field</tt> can be either the value of a name attribute (i.e. <tt>user[email]</tt>)
|
48
|
+
# or the text inside a <tt><label></tt> element that points at the <tt><input></tt> field.
|
49
|
+
def fill_in(field_locator, options = {})
|
50
|
+
field = locate_field(field_locator, TextField, TextareaField, PasswordField)
|
51
|
+
field.raise_error_if_disabled
|
52
|
+
field.set(options[:with])
|
53
|
+
end
|
54
|
+
|
55
|
+
webrat_deprecate :fills_in, :fill_in
|
56
|
+
|
57
|
+
# Verifies that a hidden field exists on the current page and sets
|
58
|
+
# the value to that given by the <tt>:to</tt> option.
|
59
|
+
#
|
60
|
+
# Example:
|
61
|
+
# set_hidden_field 'user_id', :to => 1
|
62
|
+
def set_hidden_field(field_locator, options = {})
|
63
|
+
field = locate_field(field_locator, HiddenField)
|
64
|
+
field.set(options[:to])
|
65
|
+
end
|
66
|
+
|
67
|
+
# Verifies that an input checkbox exists on the current page and marks it
|
68
|
+
# as checked, so that the value will be submitted with the form.
|
69
|
+
#
|
70
|
+
# Example:
|
71
|
+
# check 'Remember Me'
|
72
|
+
def check(field_locator)
|
73
|
+
locate_field(field_locator, CheckboxField).check
|
74
|
+
end
|
75
|
+
|
76
|
+
webrat_deprecate :checks, :check
|
77
|
+
|
78
|
+
# Verifies that an input checkbox exists on the current page and marks it
|
79
|
+
# as unchecked, so that the value will not be submitted with the form.
|
80
|
+
#
|
81
|
+
# Example:
|
82
|
+
# uncheck 'Remember Me'
|
83
|
+
def uncheck(field_locator)
|
84
|
+
locate_field(field_locator, CheckboxField).uncheck
|
85
|
+
end
|
86
|
+
|
87
|
+
webrat_deprecate :unchecks, :uncheck
|
88
|
+
|
89
|
+
# Verifies that an input radio button exists on the current page and marks it
|
90
|
+
# as checked, so that the value will be submitted with the form.
|
91
|
+
#
|
92
|
+
# Example:
|
93
|
+
# choose 'First Option'
|
94
|
+
def choose(field_locator)
|
95
|
+
locate_field(field_locator, RadioField).choose
|
96
|
+
end
|
97
|
+
|
98
|
+
webrat_deprecate :chooses, :choose
|
99
|
+
|
100
|
+
# Verifies that a an option element exists on the current page with the specified
|
101
|
+
# text. You can optionally restrict the search to a specific select list by
|
102
|
+
# assigning <tt>options[:from]</tt> the value of the select list's name or
|
103
|
+
# a label. Stores the option's value to be sent when the form is submitted.
|
104
|
+
#
|
105
|
+
# Examples:
|
106
|
+
# select "January"
|
107
|
+
# select "February", :from => "event_month"
|
108
|
+
# select "February", :from => "Event Month"
|
109
|
+
def select(option_text, options = {})
|
110
|
+
select_option(option_text, options[:from]).choose
|
111
|
+
end
|
112
|
+
|
113
|
+
webrat_deprecate :selects, :select
|
114
|
+
|
115
|
+
# Verifies that a an option element exists on the current page with the specified
|
116
|
+
# text. You can optionally restrict the search to a specific select list by
|
117
|
+
# assigning <tt>options[:from]</tt> the value of the select list's name or
|
118
|
+
# a label. Remove the option's value before the form is submitted.
|
119
|
+
#
|
120
|
+
# Examples:
|
121
|
+
# unselect "January"
|
122
|
+
# unselect "February", :from => "event_month"
|
123
|
+
# unselect "February", :from => "Event Month"
|
124
|
+
def unselect(option_text, options={})
|
125
|
+
select_option(option_text, options[:from]).unchoose
|
126
|
+
end
|
127
|
+
|
128
|
+
webrat_deprecate :unselects, :unselect
|
129
|
+
|
130
|
+
DATE_TIME_SUFFIXES = {
|
131
|
+
:year => '1i',
|
132
|
+
:month => '2i',
|
133
|
+
:day => '3i',
|
134
|
+
:hour => '4i',
|
135
|
+
:minute => '5i'
|
136
|
+
}
|
137
|
+
|
138
|
+
# Verifies that date elements (year, month, day) exist on the current page
|
139
|
+
# with the specified values. You can optionally restrict the search to a specific
|
140
|
+
# date's elements by assigning <tt>options[:from]</tt> the value of the date's
|
141
|
+
# label. Selects all the date elements with date provided. The date provided may
|
142
|
+
# be a string or a Date/Time object.
|
143
|
+
#
|
144
|
+
# Rail's convention is used for detecting the date elements. All elements
|
145
|
+
# are assumed to have a shared prefix. You may also specify the prefix
|
146
|
+
# by assigning <tt>options[:id_prefix]</tt>.
|
147
|
+
#
|
148
|
+
# Examples:
|
149
|
+
# select_date "January 23, 2004"
|
150
|
+
# select_date "April 26, 1982", :from => "Birthday"
|
151
|
+
# select_date Date.parse("December 25, 2000"), :from => "Event"
|
152
|
+
# select_date "April 26, 1982", :id_prefix => 'birthday'
|
153
|
+
def select_date(date_to_select, options ={})
|
154
|
+
date = date_to_select.is_a?(Date) || date_to_select.is_a?(Time) ?
|
155
|
+
date_to_select : Date.parse(date_to_select)
|
156
|
+
|
157
|
+
id_prefix = locate_id_prefix(options) do
|
158
|
+
year_field = FieldByIdLocator.new(@session, dom, /(.*?)_#{DATE_TIME_SUFFIXES[:year]}$/).locate
|
159
|
+
raise NotFoundError.new("No date fields were found") unless year_field && year_field.id =~ /(.*?)_1i/
|
160
|
+
$1
|
161
|
+
end
|
162
|
+
|
163
|
+
select date.year, :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:year]}"
|
164
|
+
select date.strftime('%B'), :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:month]}"
|
165
|
+
select date.day, :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:day]}"
|
166
|
+
end
|
167
|
+
|
168
|
+
webrat_deprecate :selects_date, :select_date
|
169
|
+
|
170
|
+
# Verifies that time elements (hour, minute) exist on the current page
|
171
|
+
# with the specified values. You can optionally restrict the search to a specific
|
172
|
+
# time's elements by assigning <tt>options[:from]</tt> the value of the time's
|
173
|
+
# label. Selects all the time elements with date provided. The time provided may
|
174
|
+
# be a string or a Time object.
|
175
|
+
#
|
176
|
+
# Rail's convention is used for detecting the time elements. All elements are
|
177
|
+
# assumed to have a shared prefix. You may specify the prefix by assigning
|
178
|
+
# <tt>options[:id_prefix]</tt>.
|
179
|
+
#
|
180
|
+
# Note: Just like Rails' time_select helper this assumes the form is using
|
181
|
+
# 24 hour select boxes, and not 12 hours with AM/PM.
|
182
|
+
#
|
183
|
+
# Examples:
|
184
|
+
# select_time "9:30"
|
185
|
+
# select_date "3:30PM", :from => "Party Time"
|
186
|
+
# select_date Time.parse("10:00PM"), :from => "Event"
|
187
|
+
# select_date "10:30AM", :id_prefix => 'meeting'
|
188
|
+
def select_time(time_to_select, options ={})
|
189
|
+
time = time_to_select.is_a?(Time) ? time_to_select : Time.parse(time_to_select)
|
190
|
+
|
191
|
+
id_prefix = locate_id_prefix(options) do
|
192
|
+
hour_field = FieldByIdLocator.new(@session, dom, /(.*?)_#{DATE_TIME_SUFFIXES[:hour]}$/).locate
|
193
|
+
raise NotFoundError.new("No time fields were found") unless hour_field && hour_field.id =~ /(.*?)_4i/
|
194
|
+
$1
|
195
|
+
end
|
196
|
+
|
197
|
+
select time.hour.to_s.rjust(2,'0'), :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:hour]}"
|
198
|
+
select time.min.to_s.rjust(2,'0'), :from => "#{id_prefix}_#{DATE_TIME_SUFFIXES[:minute]}"
|
199
|
+
end
|
200
|
+
|
201
|
+
webrat_deprecate :selects_time, :select_time
|
202
|
+
|
203
|
+
# Verifies and selects all the date and time elements on the current page.
|
204
|
+
# See #select_time and #select_date for more details and available options.
|
205
|
+
#
|
206
|
+
# Examples:
|
207
|
+
# select_datetime "January 23, 2004 10:30AM"
|
208
|
+
# select_datetime "April 26, 1982 7:00PM", :from => "Birthday"
|
209
|
+
# select_datetime Time.parse("December 25, 2000 15:30"), :from => "Event"
|
210
|
+
# select_datetime "April 26, 1982 5:50PM", :id_prefix => 'birthday'
|
211
|
+
def select_datetime(time_to_select, options ={})
|
212
|
+
time = time_to_select.is_a?(Time) ? time_to_select : Time.parse(time_to_select)
|
213
|
+
|
214
|
+
options[:id_prefix] ||= (options[:from] ? FieldByIdLocator.new(@session, dom, options[:from]).locate : nil)
|
215
|
+
|
216
|
+
select_date time, options
|
217
|
+
select_time time, options
|
218
|
+
end
|
219
|
+
|
220
|
+
webrat_deprecate :selects_datetime, :select_datetime
|
221
|
+
|
222
|
+
# Verifies that an input file field exists on the current page and sets
|
223
|
+
# its value to the given +file+, so that the file will be uploaded
|
224
|
+
# along with the form. An optional <tt>content_type</tt> may be given.
|
225
|
+
#
|
226
|
+
# Example:
|
227
|
+
# attach_file "Resume", "/path/to/the/resume.txt"
|
228
|
+
# attach_file "Photo", "/path/to/the/image.png", "image/png"
|
229
|
+
def attach_file(field_locator, path, content_type = nil)
|
230
|
+
locate_field(field_locator, FileField).set(path, content_type)
|
231
|
+
end
|
232
|
+
|
233
|
+
webrat_deprecate :attaches_file, :attach_file
|
234
|
+
|
235
|
+
# Issues a request for the URL pointed to by an <tt>area</tt> tag
|
236
|
+
# on the current page, follows any redirects, and verifies the
|
237
|
+
# final page load was successful.
|
238
|
+
#
|
239
|
+
# The area used is the first area whose title or id contains the
|
240
|
+
# given +area_name+ (case is ignored).
|
241
|
+
#
|
242
|
+
# Example:
|
243
|
+
# click_area 'Australia'
|
244
|
+
def click_area(area_name)
|
245
|
+
find_area(area_name).click
|
246
|
+
end
|
247
|
+
|
248
|
+
webrat_deprecate :clicks_area, :click_area
|
249
|
+
|
250
|
+
# Issues a request for the URL pointed to by a link on the current page,
|
251
|
+
# follows any redirects, and verifies the final page load was successful.
|
252
|
+
#
|
253
|
+
# click_link has very basic support for detecting Rails-generated
|
254
|
+
# JavaScript onclick handlers for PUT, POST and DELETE links, as well as
|
255
|
+
# CSRF authenticity tokens if they are present.
|
256
|
+
#
|
257
|
+
# Javascript imitation can be disabled by passing the option :javascript => false
|
258
|
+
#
|
259
|
+
# Passing a :method in the options hash overrides the HTTP method used
|
260
|
+
# for making the link request
|
261
|
+
#
|
262
|
+
# It will try to find links by (in order of precedence):
|
263
|
+
# innerHTML, with simple handling
|
264
|
+
# title
|
265
|
+
# id
|
266
|
+
#
|
267
|
+
# innerHTML and title are matchable by text subtring or Regexp
|
268
|
+
# id is matchable by full text equality or Regexp
|
269
|
+
#
|
270
|
+
# Example:
|
271
|
+
# click_link "Sign up"
|
272
|
+
# click_link "Sign up", :javascript => false
|
273
|
+
# click_link "Sign up", :method => :put
|
274
|
+
def click_link(text_or_title_or_id, options = {})
|
275
|
+
find_link(text_or_title_or_id).click(options)
|
276
|
+
end
|
277
|
+
|
278
|
+
webrat_deprecate :clicks_link, :click_link
|
279
|
+
|
280
|
+
# Verifies that a submit button exists for the form, then submits the form, follows
|
281
|
+
# any redirects, and verifies the final page was successful.
|
282
|
+
#
|
283
|
+
# Example:
|
284
|
+
# click_button "Login"
|
285
|
+
# click_button
|
286
|
+
#
|
287
|
+
# The URL and HTTP method for the form submission are automatically read from the
|
288
|
+
# <tt>action</tt> and <tt>method</tt> attributes of the <tt><form></tt> element.
|
289
|
+
def click_button(value = nil)
|
290
|
+
find_button(value).click
|
291
|
+
end
|
292
|
+
|
293
|
+
webrat_deprecate :clicks_button, :click_button
|
294
|
+
|
295
|
+
# Submit the form with the given id.
|
296
|
+
#
|
297
|
+
# Note that +click_button+ is usually preferrable for simulating
|
298
|
+
# form submissions, as you may specify part of the button text
|
299
|
+
# rather than the form id.
|
300
|
+
#
|
301
|
+
# Example:
|
302
|
+
# submit_form 'login'
|
303
|
+
def submit_form(id)
|
304
|
+
FormLocator.new(@session, dom, id).locate.submit
|
305
|
+
end
|
306
|
+
|
307
|
+
def dom # :nodoc:
|
308
|
+
return @dom if @dom
|
309
|
+
|
310
|
+
if @selector
|
311
|
+
@dom = scoped_dom
|
312
|
+
else
|
313
|
+
@dom = page_dom
|
314
|
+
end
|
315
|
+
|
316
|
+
return @dom
|
317
|
+
end
|
318
|
+
|
319
|
+
protected
|
320
|
+
|
321
|
+
def page_dom #:nodoc:
|
322
|
+
return @response.dom if @response.respond_to?(:dom)
|
323
|
+
|
324
|
+
if @session.xml_content_type?
|
325
|
+
dom = Webrat::XML.xml_document(@response_body)
|
326
|
+
else
|
327
|
+
dom = Webrat::XML.html_document(@response_body)
|
328
|
+
end
|
329
|
+
|
330
|
+
Webrat::XML.define_dom_method(@response, dom)
|
331
|
+
return dom
|
332
|
+
end
|
333
|
+
|
334
|
+
def scoped_dom
|
335
|
+
@scope.dom.css(@selector).first
|
336
|
+
end
|
337
|
+
|
338
|
+
def locate_field(field_locator, *field_types) #:nodoc:
|
339
|
+
if field_locator.is_a?(Field)
|
340
|
+
field_locator
|
341
|
+
else
|
342
|
+
field(field_locator, *field_types)
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
def locate_id_prefix(options, &location_strategy) #:nodoc:
|
347
|
+
return options[:id_prefix] if options[:id_prefix]
|
348
|
+
|
349
|
+
if options[:from]
|
350
|
+
if (label = LabelLocator.new(@session, dom, options[:from]).locate)
|
351
|
+
label.for_id
|
352
|
+
else
|
353
|
+
raise NotFoundError.new("Could not find the label with text #{options[:from]}")
|
354
|
+
end
|
355
|
+
else
|
356
|
+
yield
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
def forms #:nodoc:
|
361
|
+
@forms ||= Form.load_all(@session, dom)
|
362
|
+
end
|
363
|
+
|
364
|
+
end
|
365
|
+
end
|