Compare commits

...

113 Commits

Author SHA1 Message Date
John Bintz 5e4ffeae9f ensure query strings are built correctly for mechanize 2010-06-01 14:29:57 -04:00
John Bintz 0856d8d405 potential fix for invalid query string construction 2010-06-01 14:10:39 -04:00
Bryan Helmkamp 8f637e6785 Bumping version to prerelease until next release 2010-04-26 22:15:41 -04:00
Bryan Helmkamp 312c175384 Releasing v0.7.1 2010-04-26 22:10:16 -04:00
Damian Janowski 7cde0573c0 Update changelog. 2010-04-23 13:19:45 -03:00
Luismi Cavalle 43b19eeafa Fix have_xpath not matching negative expectation in the block.
[#182 state:resolved]
2010-04-23 13:17:49 -03:00
Damian Janowski 107bdf7cf9 Update Gemfile to the newest Bundler. 2010-04-23 13:15:30 -03:00
Damian Janowski 71a281066e Update changelog. 2010-04-23 13:09:05 -03:00
Damian Janowski 438e53c295 Fix broken integration test in 1.9.1-p378. 2010-04-22 19:09:45 -03:00
Noah Davis 80ea640901 Fix selenium webrat tests in FF/Safari -- locatedLabel.htmlFor returns empty string in FF/Safari which breaks location strategy for label 2010-04-20 23:46:43 -04:00
Noah Davis 68d5fde17a Move verbose selenium output that can clutter build output behind setting 2010-04-20 11:44:55 -04:00
Damian Janowski 1979a7fc7f Use `htmlFor` on IE.
[#317 state:resolved]
2010-04-15 15:40:03 -03:00
Álvaro Gil 06bb72d24f fix post method in mechanize adapter to handle data as array or hash
it fixes spec/integration/mechanize/sample_app.rb:20
2010-04-13 15:40:24 -03:00
Damian Janowski c49123c772 Fix Mechanize spec. 2010-04-13 13:25:28 -03:00
Damian Janowski 2c9de38129 Add missing spec that shows a regression after e3bcf5. 2010-04-13 12:57:25 -03:00
Damian Janowski 2a6c67b17b Fix delegation of `response_headers` method.
[#332 state:resolved]
2010-04-13 12:04:36 -03:00
Damian Janowski 38e699820f Merge remote branch 'wemrysi/master' into mechanize_redirects
Conflicts:
	lib/webrat/adapters/mechanize.rb
2010-04-13 12:01:22 -03:00
Damian Janowski 4c62279fc1 The WWW namespace is deprecated as of Mechanize 1.0.
[#368 state:resolved]
2010-04-12 23:38:04 -03:00
Damian Janowski deccefa2c3 Some explicit requires of RubyGems are necessary for integration tests.
Should not affect the way Webrat behaves as a library.
2010-04-12 23:30:56 -03:00
Simon Rozet 10c70a37de Get rid of needless require "rubygems" 2010-04-12 22:28:14 -03:00
Damian Janowski 19fc2ccb89 Remove warnings [#372 state:resolved].
On why this is important:
http://eigenclass.org/hiki/ruby-warnings-SEX-and-stds
2010-04-12 22:25:53 -03:00
Larry Marburger fd944cccb5 Webrat::Core::Session#redirect? should not mistake a 304 for a redirect. 2010-04-12 17:52:09 -03:00
Damian Janowski 0bbf163d4f Better stack traces when using class_eval (Alex Chaffee). 2010-04-12 17:45:10 -03:00
Damian Janowski ef6874c855 Allow submitting forms by CSS selectors too.
Priority is given to selecting by ID for backwards compatibility.

Also add pending `submit_form` specs.
2010-04-12 17:35:12 -03:00
Damian Janowski e3bcf5c599 Merge branch 'nested_params_support' 2010-04-12 17:22:54 -03:00
Damian Janowski bd6cd436de Point users in the right direction when selenium is not available. 2010-04-12 16:39:27 -03:00
Álvaro Gil e36487458f test added for nested params files upload 2010-04-09 11:38:33 -03:00
Álvaro Gil c49e23d81d fixes #341 attach_file with nested attributes 2010-04-05 11:31:38 -03:00
Álvaro Gil 15102bd60d !trivial: define and call class methods in From appropriate 2010-04-05 11:07:35 -03:00
Álvaro Gil fa881a88c8 build querystring with all form elements and then parse to get query params
* Basically Field#to_param was replaced for Field#to_query_string and
some methods related to build params were moved to Form class.

Before this commit the params hash was made by parsing each element
querystring to param and then merge, now we build the whole querystring
first and then parse it to get params with Rack or Rails depending of
the configure mode.
2010-04-03 12:07:16 -03:00
Noah Davis 2f12422ae8 New webrat configuration option selenium_firefox_profile which is passed to selenium server 2010-02-26 15:54:31 -05:00
Emrys Ingersoll 67febe9072 Normalize access to response headers in adapters 2010-02-20 17:06:30 -05:00
Emrys Ingersoll 56b2f342da Adding spec for disabling automatic redirects in Mechanize 2010-02-18 19:04:11 -05:00
Emrys Ingersoll b2dddf2f09 Disable the automatic following of redirects in the Mechanize instance so they can be handled by Webrat::Session 2010-02-18 18:33:22 -05:00
lukemelia d9d9cc1fcc Added application_port_for_selenium to webrat configuration. The use case is when you want to test through a web server sitting in front of your application server. 2010-01-18 09:49:44 -05:00
Noah Davis 0387d9eacc Bumping version to prerelease until next official release 2010-01-17 20:48:23 -05:00
Noah Davis d73eca71ee Releasing v 0.7.0 2010-01-17 20:44:20 -05:00
Noah Davis 8d2fa24b4a Added missing dependency "rack-test" to gemspec (LH #339) 2010-01-17 20:42:37 -05:00
Bryan Helmkamp eb3a4ff5d6 Whitespace 2010-01-17 20:35:42 -05:00
hpoydar 4ac8456a48 Replaced selenium standalone jar to fix Snow Leopard + Firefox 3.5 issue 2010-01-17 20:30:55 -05:00
Noah Davis 3159ae081f changelog update 2010-01-17 20:23:48 -05:00
Noah Davis ccaf41160c Save and open page storage directory now defaults to "tmp" under current directory if exists, otherwise current directory 2010-01-17 18:29:35 -05:00
Noah Davis d50d24e09e Documentation fix for application environment 2010-01-17 18:08:40 -05:00
Noah Davis 1874f6d395 Removed save_and_open_page's rewriting of static asset paths before saving (was not actually working) 2010-01-16 19:28:29 -05:00
Noah Davis 71dcfb327d Save and open page directory specified via configuration 2010-01-16 19:18:28 -05:00
Noah Davis db168bedec Make "should contain" ignore extra whitespace when doing string comparisons 2010-01-13 16:47:35 -05:00
lukemelia f9985cd488 Make selenium matchers handle negative match more consistently with positive match 2010-01-05 18:33:45 -05:00
Bryan Helmkamp b64d68a2a8 Bump VERSION to prerelease 2009-11-28 00:24:47 -05:00
Bryan Helmkamp 4081fe5538 Prep for 0.6.0 release 2009-11-28 00:18:58 -05:00
Bryan Helmkamp 3bd7266ab9 Merge branch 'lh_292'
Conflicts:
	History.txt
2009-11-15 16:51:23 -05:00
Bryan Helmkamp a9ff3efcd7 History 2009-11-15 16:50:46 -05:00
Michael Klett 61b0fce828 Base64 encoding of HTTP basic auth credentials should omit newlines (do not enforce a 76 character line limit)
According to RFC 2617 (http://www.ietf.org/rfc/rfc2617.txt), the 76 character line limit normally enforced by Base64 encoding should not apply to the encoding of HTTP basic authentication credentials.
2009-11-15 16:50:40 -05:00
Bryan Helmkamp f9f2a98189 History 2009-11-15 16:50:39 -05:00
David Chelimsky 51bdded2ce require 'nokogiri' in rspec-rails include file 2009-11-15 16:50:39 -05:00
Bryan Helmkamp 4de7d64776 History 2009-11-15 16:42:39 -05:00
Bryan Helmkamp 13d513837a Merge remote branch 'dchelimsky/require_nokogiri' into lh_293 2009-11-15 16:41:37 -05:00
Bryan Helmkamp ba95363486 Spec fix: Don't depend on Nokogiri #inspect output 2009-11-15 16:38:09 -05:00
Bryan Helmkamp 672bd583af Whitespace 2009-11-15 16:29:44 -05:00
Bryan Helmkamp 0536360773 History 2009-11-15 16:29:27 -05:00
Jonathan Weiss ea4a52ccf1 add support for Rails 2.3.4 form authenticity tokens 2009-11-15 16:24:56 -05:00
Bryan Helmkamp cbb07306d4 Regenerate gemspec with thor tasks 2009-11-15 16:07:38 -05:00
Bryan Helmkamp 5a05d860ec Use simple Thor tasks for release management instead of Jeweler 2009-11-15 15:49:38 -05:00
Bryan Helmkamp 05af4dd2a0 Switching to Safari until Snow Leopard + Firefox + Selenium is fixed
http://jira.openqa.org/browse/SRC-743
2009-11-13 21:23:27 -05:00
Bryan Helmkamp 7812f25741 Don't blow up if PID doesn't exist at the end 2009-11-13 21:22:41 -05:00
Bryan Helmkamp fcde80f43f Avoid Selenium test bleed by ending with an assertion about the next page 2009-11-13 21:17:41 -05:00
Bryan Helmkamp 1ce72b6912 Ending selenium tests with assertions avoids "test bleed" 2009-11-13 21:10:25 -05:00
Bryan Helmkamp bb282d992e Remove a couple more bogus tests
<input type="button" /> doesn't submit forms
2009-11-13 21:07:21 -05:00
Bryan Helmkamp f6dd24f7c5 Remove bogus integration tests that were passing (sometimes) by coincidence
An element of <button type="button" /> is not supposed to submit a form
2009-11-13 20:57:55 -05:00
Bryan Helmkamp d0cadf8a76 Update file location for Rails 2.3.4 2009-11-13 20:52:14 -05:00
Bryan Helmkamp 1c28425583 Use Bundler for managing dependencies needed to run the tests 2009-11-13 17:41:33 -05:00
David Chelimsky 9a92afedff require 'nokogiri' in rspec-rails include file 2009-09-23 23:04:43 -05:00
Bryan Helmkamp f51b745e89 When a timeout occurs in wait_for, include the HTML from Selenium in the exception 2009-09-22 15:23:49 -04:00
Bryan Helmkamp 8dacd973aa Regenerated gemspec for version 0.6.rc1 2009-09-22 12:44:56 -04:00
Bryan Helmkamp 194d3250cc Prep for 0.6.rc1 release 2009-09-22 12:41:57 -04:00
Bryan Helmkamp b68c6859e8 History 2009-09-22 12:41:41 -04:00
Bryan Helmkamp 87c54dde2e Fix typo in Rakefile 2009-09-19 17:57:35 -04:00
Bryan Helmkamp 042b416092 Whitespace 2009-09-19 17:34:09 -04:00
Bryan Helmkamp 40d7f970e0 Gracefully handle cases where RSpec is not installed in Rakefile 2009-09-19 17:32:42 -04:00
Bryan Helmkamp 03f2023117 Make link location in Selenium more reliable and consistent with non-Selenium 2009-09-18 15:49:06 -04:00
Bryan Helmkamp b51ba029db Fix support for passing in an ActiveRecord model to within (which uses dom_id) LB/BH 2009-09-18 11:28:07 -04:00
Bryan Helmkamp 862471476f Run Selenium tests during spec:integration 2009-09-17 22:13:10 -04:00
Bryan Helmkamp c689166c48 Fix "element.getAttribute is not a function" Selenium errors when filling in fields
The root cause was the locator strategy was naively returning an element that was not a form field, causing Selenium's internals to blow up
2009-09-17 21:32:56 -04:00
Bryan Helmkamp 3a9e7d3999 Fix bugs when dealing with special characters in labels 2009-09-17 21:18:52 -04:00
Bryan Helmkamp 63e1053afa Fix bug in Selenium when dealing with special characters in link text 2009-09-17 20:28:19 -04:00
Bryan Helmkamp aae82b5111 Whitespace 2009-09-17 20:15:40 -04:00
Bryan Helmkamp e7a3ac865c Guard tests for things that aren't supported in Selenium yet 2009-09-17 20:13:04 -04:00
Bryan Helmkamp 8772505322 History 2009-09-07 14:16:23 -04:00
Bryan Helmkamp b0ef59f5ec Properly handle multiline param values (previously, subsequent lines were lost) 2009-09-07 14:07:05 -04:00
Bryan Helmkamp ad06a777fb Re-introduce VERSION constant, but don't make it dependent on the VERSION file 2009-09-07 13:25:33 -04:00
Bryan Helmkamp 756a0c62ba Make build task depend on gemspec. Closes GH issue #15 2009-09-07 13:22:57 -04:00
Bryan Helmkamp 63591a8c30 History 2009-09-07 13:18:57 -04:00
Bryan Helmkamp ecaed5ff93 Merge commit 'm3talsmith/master' into gh_18 2009-09-07 13:16:53 -04:00
Bryan Helmkamp b0a8922eb4 History 2009-09-07 13:08:34 -04:00
Bryan Helmkamp 2490c247d2 More clarification of select option locating behavior.
TODO: Ensure the other locators are all matching on text, not HTML
2009-09-07 12:53:06 -04:00
Bryan Helmkamp 00c49a0521 Simplify select option matching code. Minor behavior change:
Valid: select "Peanut Butter & Jelly"
  Invalid: select "Peanut Butter &amp; Jelly"
2009-09-07 12:44:54 -04:00
Bryan Helmkamp b7ea26841e Add some development dependencies (needed for running the specs) 2009-09-07 12:44:42 -04:00
Kieran Pilkington a8d0cebde3 Various improvements, refinements, and bugfixes for select field usage.
Multiple select boxes are now handled a lot better.
* You can now select more than one field (where as previously, the last one select would override previous selections)
* You can now unselect a value. It works like select, takes the same params, but removes the selection value

Issues regarding ampersands in values have been resolved.
* Values are now unescaped when the to_param method is run on elements, to make assertions less complicated
* Locating an option with ampersand values now works as expected (it will check for both escaped and unescaped occurrences)

Bunch of new specs and 3 broken pending ones have now been fixed. [#145 status:resolved]
2009-08-31 18:34:04 +12:00
Bryan Helmkamp 98efa54900 Whitespace 2009-08-29 16:09:30 -04:00
Bryan Helmkamp 49c25027e9 History 2009-08-29 16:05:56 -04:00
Bryan Helmkamp 6fd9732b4e Spec giving me trouble -- removing for now 2009-08-29 16:04:04 -04:00
Bryan Helmkamp b9466df773 Merge commit 'djanowski/fix_logger' 2009-08-29 15:57:58 -04:00
Michael Christenson II 3255c9edf0 Forces an integer to fix Issue #18 2009-08-27 11:54:03 -04:00
Bryan Helmkamp 5b90488f29 Revert "Regenerated gemspec for version 0.5.2"
This reverts commit f1cd50d615.
2009-08-27 01:02:01 -04:00
Bryan Helmkamp f1cd50d615 Regenerated gemspec for version 0.5.2 2009-08-27 00:59:53 -04:00
Bryan Helmkamp e18ef197b5 Move selenium integration code to webrat/integrations/selenium so it's automatically required 2009-08-20 00:09:03 -04:00
Bryan Helmkamp 755abb7e07 History 2009-08-19 23:44:33 -04:00
Bryan Helmkamp 723f4356b9 Move rspec-rails integration code to webrat/integrations/rspec-rails 2009-08-19 23:42:58 -04:00
Bryan Helmkamp 2fc9f3f7f9 Move adapters to webrat/adapters, and Rails and Merb integration code into webrat/integrations 2009-08-19 23:42:54 -04:00
Bryan Helmkamp 610f0fc217 Webrat doesn't need to worry about StringIOs
...or, we're missing a test and this is going to help us find it
2009-08-19 23:14:13 -04:00
Bryan Helmkamp 11f30d1d2e Dropping support for Hpricot and REXML 2009-08-19 23:14:13 -04:00
Simon Rozet 997ff97405 MerbSession now use RackSession under the hood 2009-08-19 23:14:08 -04:00
Bryan Helmkamp ab745d786c Require rubygems in rakefile for convenience
This does not break the "Don't require rubygems" spirit,
because it's not creating a dependency in the Webrat runtime code
2009-08-19 22:02:19 -04:00
Damian Janowski 4a949e0e5a Fix logger issue when running inside Cucumber. 2009-08-14 13:05:20 -03:00
110 changed files with 1766 additions and 1483 deletions

5
.gitignore vendored
View File

@ -12,4 +12,7 @@ log
results results
test_apps test_apps
*.tmproj *.tmproj
*.log *.log
*.pid
bin
vendor/gems

13
Gemfile Normal file
View File

@ -0,0 +1,13 @@
gem "rake", "0.8.7"
gem "rspec", "1.2.9"
gem "diff-lcs", "1.1.2"
gem "rack", "1.0.1"
gem "nokogiri", "1.4.0"
gem "merb-core", "1.0.15"
gem "selenium-client", "1.2.17"
gem "mechanize", "0.9.3"
gem "rails", "2.3.4"
gem "launchy", "0.3.3"
gem "rack-test", "0.5.2"
gem "sinatra", "0.9.4"
gem "mongrel", "1.1.5"

View File

@ -1,3 +1,72 @@
== 0.7.1 / 2010-04-26
* Minor enhancements
* Move verbose selenium output that can clutter build output behind setting
* Added application_port_for_selenium to webrat configuration. The use case is when you want to test through a web server sitting in front of your application server. (Luke Melia)
* New webrat configuration option selenium_firefox_profile which is passed to selenium server
* Allow submit_form to select by CSS too (Damian Janowski)
* Bug fixes
* Fix that current_url wasn't reflecting redirects in Mechanize [#332] (Emrys Ingersoll)
* Fix attach_file with nested params [#341] (Álvaro Gil)
* Fix that a 304 was considered a redirect (Larry Marburger)
* Fix selection of LABEL elements in Selenium mode under IE [#317] (Damian Janowski, Noah Davis)
* Fix have_xpath not matching negative expectation in the block [#182] (Luismi Cavallé)
== 0.7.0 / 2010-01-17
* Major enhancements
* Upgrade bundled Selenium server JAR to 2.0a1 (Henry Poydar and Jake Scruggs)
* Minor enhancements
* Save and open page directory specified via configuration, defaults to tmp dir otherwise current dir (Noah Davis)
* Bug fixes
* Added missing dependency "rack-test" to gemspec (LH #339) (Noah Davis)
* Removed save_and_open_page's rewriting of static asset paths before saving (was not actually working) (Noah Davis)
* Make "should contain" ignore extra whitespace when doing string comparisons (Noah Davis)
* Make selenium matchers handle negative match more consistently with positive match (Luke Melia)
== 0.6.0 / 2009-11-28
REMOVED: Support for Hpricot + REXML as an alternative to Nokogiri.
Hpricot and REXML were difficult to work with, REXML is terribly slow,
and Nokogiri is recommended even by the author of Hpricot (_why). Now
that Nokogiri works on JRuby, Webrat is going to use it as its sole
XML backend.
CHANGED: Due to a reorganization, if you're currently requiring "webrat/rspec-rails",
please change your code to require "webrat/integrations/rspec-rails"
* Minor enhancements
* Support Rails 2.3.4 JavaScript form authenticity tokens in simulated mode (Jonathan Weiss)
* When a timeout occurs in wait_for, include the HTML from Selenium in the exception
* Update the Merb support to be based directly on Rack (Simon Rozet)
* Support multiple select fields (Kieran P)
* When locating select options, always match against text, not HTML
* Bug fixes
* Remove newlines from HTTP Basic authentication credentials (Michael Klett)
* Require nokogiri form rspec-rails.rb (David Chelimsky)
* Fix logger issue when running inside Cucumber (Damian Janowski)
* Fix various issues related to submitting values with HTML entities (Kieran P)
* Call #to_i on the :count option in matchers (Michael Christenson II)
* Fix bug where multiline param values were getting truncated
== 0.5.3 / 2009-08-27
* Minor enhancements
* Remove unnecessary requires which are to the wrong paths on Edge Rails
== 0.5.1 / 2009-08-18 == 0.5.1 / 2009-08-18
* Minor enhancements * Minor enhancements

102
Rakefile
View File

@ -1,58 +1,24 @@
begin begin
require 'jeweler' require 'spec/rake/spectask'
Jeweler::Tasks.new do |s|
s.name = "webrat"
s.author = "Bryan Helmkamp"
s.email = "bryan" + "@" + "brynary.com"
s.homepage = "http://github.com/brynary/webrat"
s.summary = "Ruby Acceptance Testing for Web applications"
s.description = <<-EOS.strip
Webrat lets you quickly write expressive and robust acceptance tests
for a Ruby web application. It supports simulating a browser inside
a Ruby process to avoid the performance hit and browser dependency of
Selenium or Watir, but the same API can also be used to drive real
Selenium tests when necessary (eg. for testing AJAX interactions).
Most Ruby web frameworks and testing frameworks are supported.
EOS
s.rubyforge_project = "webrat"
s.extra_rdoc_files = %w[README.rdoc MIT-LICENSE.txt History.txt]
# Dependencies
s.add_dependency "nokogiri", ">= 1.2.0"
s.add_dependency "rack", ">= 1.0"
# TODO: Add development dependencies
end
Jeweler::RubyforgeTasks.new
rescue LoadError rescue LoadError
puts "Jeweler not available. Install it with: gem install jeweler" desc "Run specs"
end task(:spec) { $stderr.puts '`gem install rspec` to run specs' }
else
# require 'spec' desc "Run API and Core specs"
require 'spec/rake/spectask' Spec::Rake::SpecTask.new do |t|
require 'spec/rake/verify_rcov' t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
t.spec_files = FileList['spec/public/**/*_spec.rb'] + FileList['spec/private/**/*_spec.rb']
desc "Run API and Core specs"
Spec::Rake::SpecTask.new do |t|
t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
t.spec_files = FileList['spec/public/**/*_spec.rb'] + FileList['spec/private/**/*_spec.rb']
end
desc "Run all specs in spec directory with RCov"
Spec::Rake::SpecTask.new(:rcov) do |t|
t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
t.spec_files = FileList['spec/public/**/*_spec.rb'] + FileList['spec/private/**/*_spec.rb']
t.rcov = true
t.rcov_opts = lambda do
IO.readlines(File.dirname(__FILE__) + "/spec/rcov.opts").map {|l| l.chomp.split " "}.flatten
end end
end
RCov::VerifyTask.new(:verify_rcov => :rcov) do |t| desc "Run all specs in spec directory with RCov"
t.threshold = 96.2 # Make sure you have rcov 0.7 or higher! Spec::Rake::SpecTask.new(:rcov) do |t|
t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
t.spec_files = FileList['spec/public/**/*_spec.rb'] + FileList['spec/private/**/*_spec.rb']
t.rcov = true
t.rcov_opts = lambda do
IO.readlines(File.dirname(__FILE__) + "/spec/rcov.opts").map {|l| l.chomp.split " "}.flatten
end
end
end end
desc "Run everything against multiruby" desc "Run everything against multiruby"
@ -107,29 +73,29 @@ task :spec_deps do
end end
end end
task :prepare do
system "ln -s ../../../../.. ./spec/integration/rails/vendor/plugins/webrat"
end
namespace :spec do namespace :spec do
desc "Run the integration specs" desc "Run the integration specs"
task :integration => ["integration:rails", "integration:merb", "integration:sinatra", "integration:rack", "integration:mechanize"] task :integration => [
"integration:rack",
"integration:sinatra",
"integration:merb",
"integration:mechanize",
"integration:rails:webrat",
"integration:rails:selenium",
]
namespace :integration do namespace :integration do
desc "Run the Rails integration specs"
task :rails => ['rails:webrat'] #,'rails:selenium'] currently not running selenium as it doesn't pass.
namespace :rails do namespace :rails do
task :selenium do task :selenium do
Dir.chdir "spec/integration/rails" do Dir.chdir "spec/integration/rails" do
result = system "rake test_unit:selenium" result = system "rake -rubygems test_unit:selenium"
raise "Rails integration tests failed" unless result raise "Rails integration tests failed" unless result
end end
end end
task :webrat do task :webrat do
Dir.chdir "spec/integration/rails" do Dir.chdir "spec/integration/rails" do
result = system "rake test_unit:rails" result = system "rake -rubygems test_unit:rails"
raise "Rails integration tests failed" unless result raise "Rails integration tests failed" unless result
end end
end end
@ -138,7 +104,7 @@ namespace :spec do
desc "Run the Merb integration specs" desc "Run the Merb integration specs"
task :merb do task :merb do
Dir.chdir "spec/integration/merb" do Dir.chdir "spec/integration/merb" do
result = system "rake spec" result = system "rake -rubygems spec"
raise "Merb integration tests failed" unless result raise "Merb integration tests failed" unless result
end end
end end
@ -146,7 +112,7 @@ namespace :spec do
desc "Run the Sinatra integration specs" desc "Run the Sinatra integration specs"
task :sinatra do task :sinatra do
Dir.chdir "spec/integration/sinatra" do Dir.chdir "spec/integration/sinatra" do
result = system "rake test" result = system "rake -rubygems test"
raise "Sinatra integration tests failed" unless result raise "Sinatra integration tests failed" unless result
end end
end end
@ -154,7 +120,7 @@ namespace :spec do
desc "Run the Sinatra integration specs" desc "Run the Sinatra integration specs"
task :rack do task :rack do
Dir.chdir "spec/integration/rack" do Dir.chdir "spec/integration/rack" do
result = system "rake test" result = system "rake -rubygems test"
raise "Rack integration tests failed" unless result raise "Rack integration tests failed" unless result
end end
end end
@ -162,7 +128,7 @@ namespace :spec do
desc "Run the Mechanize integration specs" desc "Run the Mechanize integration specs"
task :mechanize do task :mechanize do
Dir.chdir "spec/integration/mechanize" do Dir.chdir "spec/integration/mechanize" do
result = system "rake spec" result = system "rake -rubygems spec"
raise "Mechanize integration tests failed" unless result raise "Mechanize integration tests failed" unless result
end end
end end
@ -174,8 +140,4 @@ task :whitespace do
sh %{find . -name '*.rb' -exec sed -i '' 's/ *$//g' {} \\;} sh %{find . -name '*.rb' -exec sed -i '' 's/ *$//g' {} \\;}
end end
if defined?(Jeweler) task :default => :spec
task :spec => :check_dependencies
end
task :default => :spec

118
Thorfile Normal file
View File

@ -0,0 +1,118 @@
module GemHelpers
def generate_gemspec
$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), "lib")))
require "webrat"
Gem::Specification.new do |s|
s.name = "webrat"
s.version = Webrat::VERSION
s.author = "Bryan Helmkamp"
s.email = "bryan@brynary.com"
s.homepage = "http://github.com/brynary/webrat"
s.summary = "Ruby Acceptance Testing for Web applications"
s.description = <<-EOS.strip
Webrat lets you quickly write expressive and robust acceptance tests
for a Ruby web application. It supports simulating a browser inside
a Ruby process to avoid the performance hit and browser dependency of
Selenium or Watir, but the same API can also be used to drive real
Selenium tests when necessary (eg. for testing AJAX interactions).
Most Ruby web frameworks and testing frameworks are supported.
EOS
s.rubyforge_project = "webrat"
require "git"
repo = Git.open(".")
s.files = normalize_files(repo.ls_files.keys - repo.lib.ignored_files)
s.test_files = normalize_files(Dir['spec/**/*.rb'] - repo.lib.ignored_files)
s.has_rdoc = true
s.extra_rdoc_files = %w[README.rdoc MIT-LICENSE.txt History.txt]
s.add_dependency "nokogiri", ">= 1.2.0"
s.add_dependency "rack", ">= 1.0"
s.add_dependency "rack-test", ">= 0.5.3"
end
end
def normalize_files(array)
# only keep files, no directories, and sort
array.select do |path|
File.file?(path)
end.sort
end
# Adds extra space when outputting an array. This helps create better version
# control diffs, because otherwise it is all on the same line.
def prettyify_array(gemspec_ruby, array_name)
gemspec_ruby.gsub(/s\.#{array_name.to_s} = \[.+?\]/) do |match|
leadin, files = match[0..-2].split("[")
leadin + "[\n #{files.split(",").join(",\n ")}\n ]"
end
end
def read_gemspec
@read_gemspec ||= eval(File.read("webrat.gemspec"))
end
def sh(command)
puts command
system command
end
end
class Default < Thor
include GemHelpers
desc "gemspec", "Regenerate webrat.gemspec"
def gemspec
File.open("webrat.gemspec", "w") do |file|
gemspec_ruby = generate_gemspec.to_ruby
gemspec_ruby = prettyify_array(gemspec_ruby, :files)
gemspec_ruby = prettyify_array(gemspec_ruby, :test_files)
gemspec_ruby = prettyify_array(gemspec_ruby, :extra_rdoc_files)
file.write gemspec_ruby
end
puts "Wrote gemspec to webrat.gemspec"
read_gemspec.validate
end
desc "build", "Build a webrat gem"
def build
sh "gem build webrat.gemspec"
FileUtils.mkdir_p "pkg"
FileUtils.mv read_gemspec.file_name, "pkg"
end
desc "install", "Install the latest built gem"
def install
sh "gem install --local pkg/#{read_gemspec.file_name}"
end
desc "release", "Release the current branch to GitHub and Gemcutter"
def release
gemspec
build
Release.new.tag
Release.new.gem
end
end
class Release < Thor
include GemHelpers
desc "tag", "Tag the gem on the origin server"
def tag
release_tag = "v#{read_gemspec.version}"
sh "git tag -a #{release_tag} -m 'Tagging #{release_tag}'"
sh "git push origin #{release_tag}"
end
desc "gem", "Push the gem to Gemcutter"
def gem
sh "gem push pkg/#{read_gemspec.file_name}"
end
end

View File

@ -1 +0,0 @@
0.5.1

View File

@ -1,10 +1,18 @@
require "rack"
require "nokogiri"
module Webrat module Webrat
VERSION = "0.7.2.pre"
autoload :MechanizeAdapter, "webrat/adapters/mechanize"
autoload :MerbAdapter, "webrat/adapters/merb"
autoload :RackAdapter, "webrat/adapters/rack"
autoload :RailsAdapter, "webrat/adapters/rails"
autoload :SinatraAdapter, "webrat/adapters/sinatra"
# The common base class for all exceptions raised by Webrat. # The common base class for all exceptions raised by Webrat.
class WebratError < StandardError class WebratError < StandardError
end end
end end
require "rack"
require "nokogiri"
require "webrat/core/xml/nokogiri"
require "webrat/core" require "webrat/core"

View File

@ -4,6 +4,8 @@ module Webrat #:nodoc:
class MechanizeAdapter #:nodoc: class MechanizeAdapter #:nodoc:
extend Forwardable extend Forwardable
Mechanize = WWW::Mechanize if defined?(WWW::Mechanize)
attr_accessor :response attr_accessor :response
alias :page :response alias :page :response
@ -20,13 +22,19 @@ module Webrat #:nodoc:
def post(url, data, headers_argument_not_used = nil) def post(url, data, headers_argument_not_used = nil)
post_data = data.inject({}) do |memo, param| post_data = data.inject({}) do |memo, param|
case param.last case param
when Hash when Hash
param.last.each {|attribute, value| memo["#{param.first}[#{attribute}]"] = value } param.each {|attribute, value| memo[attribute] = value }
else memo
memo[param.first] = param.last when Array
case param.last
when Hash
param.last.each {|attribute, value| memo["#{param.first}[#{attribute}]"] = value }
else
memo[param.first] = param.last
end
memo
end end
memo
end end
@response = mechanize.post(url, post_data) @response = mechanize.post(url, post_data)
end end
@ -39,8 +47,16 @@ module Webrat #:nodoc:
@response.code.to_i @response.code.to_i
end end
def response_headers
@response.header
end
def mechanize def mechanize
@mechanize ||= WWW::Mechanize.new @mechanize ||= begin
mechanize = Mechanize.new
mechanize.redirect_ok = false
mechanize
end
end end
def_delegators :mechanize, :basic_auth def_delegators :mechanize, :basic_auth

View File

@ -0,0 +1,11 @@
require "webrat/integrations/merb"
module Webrat
class MerbAdapter < RackAdapter #:nodoc:
def initialize(context=nil)
app = context.respond_to?(:app) ?
context.app : Merb::Rack::Application.new
super(Rack::Test::Session.new(Rack::MockSession.new(app, "www.example.com")))
end
end
end

View File

@ -18,6 +18,10 @@ module Webrat
response.status response.status
end end
def response_headers
response.headers
end
def response def response
@session.last_response @session.last_response
end end

View File

@ -1,7 +1,4 @@
require "webrat" require "webrat/integrations/rails"
require "action_controller"
require "action_controller/integration"
require "action_controller/record_identifier" require "action_controller/record_identifier"
module Webrat module Webrat
@ -14,29 +11,6 @@ module Webrat
@integration_session = session @integration_session = session
end end
# The Rails version of within supports passing in a model and Webrat
# will apply a scope based on Rails' dom_id for that model.
#
# Example:
# within User.last do
# click_link "Delete"
# end
def within(selector_or_object, &block)
if selector_or_object.is_a?(String)
super
else
super('#' + dom_id(selector_or_object), &block)
end
end
def doc_root
File.expand_path(File.join(RAILS_ROOT, 'public'))
end
def saved_page_dir
File.expand_path(File.join(RAILS_ROOT, "tmp"))
end
def get(url, data, headers = nil) def get(url, data, headers = nil)
do_request(:get, url, data, headers) do_request(:get, url, data, headers)
end end
@ -61,6 +35,10 @@ module Webrat
response.code.to_i response.code.to_i
end end
def response_headers
response.headers
end
def xml_content_type? def xml_content_type?
response.headers["Content-Type"].to_s =~ /xml/ response.headers["Content-Type"].to_s =~ /xml/
end end
@ -97,10 +75,3 @@ module Webrat
end end
end end
end end
module ActionController #:nodoc:
IntegrationTest.class_eval do
include Webrat::Methods
include Webrat::Matchers
end
end

View File

@ -1,5 +1,3 @@
require "webrat/rack"
module Webrat module Webrat
class SinatraAdapter < RackAdapter class SinatraAdapter < RackAdapter
def initialize(context) def initialize(context)

View File

@ -1,6 +1,5 @@
require "webrat/core/configuration" require "webrat/core/configuration"
require "webrat/core/xml" require "webrat/core/xml"
require "webrat/core/xml/nokogiri"
require "webrat/core/logging" require "webrat/core/logging"
require "webrat/core/elements/form" require "webrat/core/elements/form"
require "webrat/core/scope" require "webrat/core/scope"

View File

@ -1,4 +1,5 @@
require "webrat/core_extensions/deprecate" require "webrat/core_extensions/deprecate"
require "pathname"
module Webrat module Webrat
@ -16,20 +17,20 @@ module Webrat
# Webrat can be configured using the Webrat.configure method. For example: # Webrat can be configured using the Webrat.configure method. For example:
# #
# Webrat.configure do |config| # Webrat.configure do |config|
# config.parse_with_nokogiri = false # config.mode = :sinatra
# end # end
class Configuration class Configuration
# Should XHTML be parsed with Nokogiri? Defaults to true, except on JRuby. When false, Hpricot and REXML are used
attr_writer :parse_with_nokogiri
# Webrat's mode, set automatically when requiring webrat/rails, webrat/merb, etc. # Webrat's mode, set automatically when requiring webrat/rails, webrat/merb, etc.
attr_reader :mode # :nodoc: attr_reader :mode # :nodoc:
# Save and open pages with error status codes (500-599) in a browser? Defualts to true. # Save and open pages with error status codes (500-599) in a browser? Defualts to true.
attr_writer :open_error_files attr_writer :open_error_files
# Which rails environment should the selenium tests be run in? Defaults to selenium. # Save and open page storage directory, defaults to "tmp" under current directory if exists, otherwise current directory
attr_accessor :saved_pages_dir
# Which rails environment should the selenium tests be run in? Defaults to test.
attr_accessor :application_environment attr_accessor :application_environment
webrat_deprecate :selenium_environment, :application_environment webrat_deprecate :selenium_environment, :application_environment
webrat_deprecate :selenium_environment=, :application_environment= webrat_deprecate :selenium_environment=, :application_environment=
@ -39,6 +40,13 @@ module Webrat
webrat_deprecate :selenium_port, :application_port webrat_deprecate :selenium_port, :application_port
webrat_deprecate :selenium_port=, :application_port= webrat_deprecate :selenium_port=, :application_port=
# Which port should selenium use to access the application. Defaults to application_port
attr_writer :application_port_for_selenium
def application_port_for_selenium
@application_port_for_selenium || self.application_port
end
# Which underlying app framework we're testing with selenium # Which underlying app framework we're testing with selenium
attr_accessor :application_framework attr_accessor :application_framework
@ -57,13 +65,19 @@ module Webrat
# Set the timeout for waiting for the browser process to start # Set the timeout for waiting for the browser process to start
attr_accessor :selenium_browser_startup_timeout attr_accessor :selenium_browser_startup_timeout
# Set the firefox profile for selenium to use
attr_accessor :selenium_firefox_profile
# How many redirects to the same URL should be halted as an infinite redirect # How many redirects to the same URL should be halted as an infinite redirect
# loop? Defaults to 10 # loop? Defaults to 10
attr_accessor :infinite_redirect_limit attr_accessor :infinite_redirect_limit
# Print out the full HTML on wait failure
# Defaults to false
attr_accessor :selenium_verbose_output
def initialize # :nodoc: def initialize # :nodoc:
self.open_error_files = true self.open_error_files = true
self.parse_with_nokogiri = true
self.application_environment = :test self.application_environment = :test
self.application_port = 3001 self.application_port = 3001
self.application_address = 'localhost' self.application_address = 'localhost'
@ -72,12 +86,12 @@ module Webrat
self.infinite_redirect_limit = 10 self.infinite_redirect_limit = 10
self.selenium_browser_key = '*firefox' self.selenium_browser_key = '*firefox'
self.selenium_browser_startup_timeout = 5 self.selenium_browser_startup_timeout = 5
end self.selenium_verbose_output = false
def parse_with_nokogiri? #:nodoc: tmp_dir = Pathname.new(Dir.pwd).join("tmp")
@parse_with_nokogiri ? true : false self.saved_pages_dir = tmp_dir.exist? ? tmp_dir : Dir.pwd
end end
def open_error_files? #:nodoc: def open_error_files? #:nodoc:
@open_error_files ? true : false @open_error_files ? true : false
end end
@ -87,13 +101,11 @@ module Webrat
def mode=(mode) def mode=(mode)
@mode = mode.to_sym @mode = mode.to_sym
# This is a temporary hack to support backwards compatibility begin
# with Merb 1.0.8 until it's updated to use the new Webrat.configure require("webrat/integrations/#{mode}")
# syntax rescue LoadError
if @mode == :merb # Only some modes have integration code that needs to
require("webrat/merb_adapter") # be loaded, so this is OK
else
require("webrat/#{mode}")
end end
end end

View File

@ -4,7 +4,7 @@ module Webrat
class Area < Element #:nodoc: class Area < Element #:nodoc:
def self.xpath_search def self.xpath_search
".//area" [".//area"]
end end
def click(method = nil, options = {}) def click(method = nil, options = {})
@ -14,7 +14,7 @@ module Webrat
protected protected
def href def href
Webrat::XML.attribute(@element, "href") @element["href"]
end end
def absolute_href def absolute_href

View File

@ -3,14 +3,14 @@ module Webrat
class Element # :nodoc: class Element # :nodoc:
def self.load_all(session, dom) def self.load_all(session, dom)
Webrat::XML.xpath_search(dom, xpath_search).map do |element| dom.xpath(*xpath_search).map do |element|
load(session, element) load(session, element)
end end
end end
def self.load(session, element) def self.load(session, element)
return nil if element.nil? return nil if element.nil?
session.elements[Webrat::XML.xpath_to(element)] ||= self.new(session, element) session.elements[element.path] ||= self.new(session, element)
end end
attr_reader :element attr_reader :element
@ -21,7 +21,7 @@ module Webrat
end end
def path def path
Webrat::XML.xpath_to(@element) @element.path
end end
def inspect def inspect

View File

@ -1,6 +1,7 @@
require "cgi" require "cgi"
require "digest/md5"
require "webrat/core_extensions/blank" require "webrat/core_extensions/blank"
require "webrat/core_extensions/nil_to_param" require "webrat/core_extensions/nil_to_query_string"
require "webrat/core/elements/element" require "webrat/core/elements/element"
@ -13,7 +14,7 @@ module Webrat
attr_reader :value attr_reader :value
def self.xpath_search def self.xpath_search
[".//button", ".//input", ".//textarea", ".//select"] ".//button|.//input|.//textarea|.//select"
end end
def self.xpath_search_excluding_hidden def self.xpath_search_excluding_hidden
@ -32,16 +33,21 @@ module Webrat
def self.load(session, element) def self.load(session, element)
return nil if element.nil? return nil if element.nil?
session.elements[Webrat::XML.xpath_to(element)] ||= field_class(element).new(session, element) session.elements[element.path] ||= field_class(element).new(session, element)
end end
def self.field_class(element) def self.field_class(element)
case element.name case element.name
when "button" then ButtonField when "button" then ButtonField
when "select" then SelectField when "select"
if element.attributes["multiple"].nil?
SelectField
else
MultipleSelectField
end
when "textarea" then TextareaField when "textarea" then TextareaField
else else
case Webrat::XML.attribute(element, "type") case element["type"]
when "checkbox" then CheckboxField when "checkbox" then CheckboxField
when "hidden" then HiddenField when "hidden" then HiddenField
when "radio" then RadioField when "radio" then RadioField
@ -67,11 +73,11 @@ module Webrat
end end
def id def id
Webrat::XML.attribute(@element, "id") @element["id"]
end end
def disabled? def disabled?
@element.attributes.has_key?("disabled") && Webrat::XML.attribute(@element, "disabled") != 'false' @element.attributes.has_key?("disabled") && @element["disabled"] != 'false'
end end
def raise_error_if_disabled def raise_error_if_disabled
@ -79,17 +85,17 @@ module Webrat
raise DisabledFieldError.new("Cannot interact with disabled form element (#{self})") raise DisabledFieldError.new("Cannot interact with disabled form element (#{self})")
end end
def to_param def to_query_string
return nil if disabled? return nil if disabled?
case Webrat.configuration.mode query_string = case Webrat.configuration.mode
when :rails when :rails, :merb, :rack, :sinatra
parse_rails_request_params("#{name}=#{escaped_value}") build_query_string
when :merb when :mechanize
::Merb::Parse.query("#{name}=#{escaped_value}") build_query_string(false)
else
{ name => value }
end end
query_string
end end
def set(value) def set(value)
@ -102,18 +108,6 @@ module Webrat
protected protected
def parse_rails_request_params(params)
if defined?(ActionController::AbstractRequest)
ActionController::AbstractRequest.parse_query_parameters(params)
elsif defined?(ActionController::UrlEncodedPairParser)
# For Rails > 2.2
ActionController::UrlEncodedPairParser.parse_query_parameters(params)
else
# For Rails > 2.3
Rack::Utils.parse_nested_query(params)
end
end
def form def form
Form.load(@session, form_element) Form.load(@session, form_element)
end end
@ -128,11 +122,23 @@ module Webrat
end end
def name def name
Webrat::XML.attribute(@element, "name") @element["name"]
end
def build_query_string(escape_value=true)
if @value.is_a?(Array)
@value.collect {|value| "#{name}=#{ escape_value ? escape(value) : value }" }.join("&")
else
"#{name}=#{ escape_value ? escape(value) : value }"
end
end
def escape(value)
CGI.escape(value.to_s)
end end
def escaped_value def escaped_value
CGI.escape([*@value].first.to_s) CGI.escape(@value.to_s)
end end
def labels def labels
@ -155,30 +161,14 @@ module Webrat
end end
unless id.blank? unless id.blank?
@label_elements += Webrat::XML.xpath_search(form.element, ".//label[@for = '#{id}']") @label_elements += form.element.xpath(".//label[@for = '#{id}']")
end end
@label_elements @label_elements
end end
def default_value def default_value
Webrat::XML.attribute(@element, "value") @element["value"]
end
def replace_param_value(params, oval, nval)
output = Hash.new
params.each do |key, value|
case value
when Hash
value = replace_param_value(value, oval, nval)
when Array
value = value.map { |o| o == oval ? nval : oval }
when oval
value = nval
end
output[key] = value
end
output
end end
end end
@ -188,7 +178,7 @@ module Webrat
[".//button", ".//input[@type = 'submit']", ".//input[@type = 'button']", ".//input[@type = 'image']"] [".//button", ".//input[@type = 'submit']", ".//input[@type = 'button']", ".//input[@type = 'image']"]
end end
def to_param def to_query_string
return nil if @value.nil? return nil if @value.nil?
super super
end end
@ -199,7 +189,7 @@ module Webrat
def click def click
raise_error_if_disabled raise_error_if_disabled
set(Webrat::XML.attribute(@element, "value")) unless Webrat::XML.attribute(@element, "name").blank? set(@element["value"]) unless @element["name"].blank?
form.submit form.submit
end end
@ -211,13 +201,13 @@ module Webrat
".//input[@type = 'hidden']" ".//input[@type = 'hidden']"
end end
def to_param def to_query_string
if collection_name? if collection_name?
super super
else else
checkbox_with_same_name = form.field_named(name, CheckboxField) checkbox_with_same_name = form.field_named(name, CheckboxField)
if checkbox_with_same_name.to_param.blank? if checkbox_with_same_name.to_query_string.blank?
super super
else else
nil nil
@ -239,18 +229,18 @@ module Webrat
".//input[@type = 'checkbox']" ".//input[@type = 'checkbox']"
end end
def to_param def to_query_string
return nil if @value.nil? return nil if @value.nil?
super super
end end
def check def check
raise_error_if_disabled raise_error_if_disabled
set(Webrat::XML.attribute(@element, "value") || "on") set(@element["value"] || "on")
end end
def checked? def checked?
Webrat::XML.attribute(@element, "checked") == "checked" @element["checked"] == "checked"
end end
def uncheck def uncheck
@ -261,8 +251,8 @@ module Webrat
protected protected
def default_value def default_value
if Webrat::XML.attribute(@element, "checked") == "checked" if @element["checked"] == "checked"
Webrat::XML.attribute(@element, "value") || "on" @element["value"] || "on"
else else
nil nil
end end
@ -284,7 +274,7 @@ module Webrat
".//input[@type = 'radio']" ".//input[@type = 'radio']"
end end
def to_param def to_query_string
return nil if @value.nil? return nil if @value.nil?
super super
end end
@ -295,11 +285,11 @@ module Webrat
option.set(nil) option.set(nil)
end end
set(Webrat::XML.attribute(@element, "value") || "on") set(@element["value"] || "on")
end end
def checked? def checked?
Webrat::XML.attribute(@element, "checked") == "checked" @element["checked"] == "checked"
end end
protected protected
@ -309,8 +299,8 @@ module Webrat
end end
def default_value def default_value
if Webrat::XML.attribute(@element, "checked") == "checked" if @element["checked"] == "checked"
Webrat::XML.attribute(@element, "value") || "on" @element["value"] || "on"
else else
nil nil
end end
@ -327,7 +317,7 @@ module Webrat
protected protected
def default_value def default_value
Webrat::XML.inner_html(@element) @element.inner_html
end end
end end
@ -341,33 +331,32 @@ module Webrat
attr_accessor :content_type attr_accessor :content_type
def set(value, content_type = nil) def set(value, content_type = nil)
@original_value = @value
@content_type ||= content_type
super(value) super(value)
@content_type = content_type
end end
def to_param def digest_value
if @value.nil? @value ? Digest::MD5.hexdigest(self.object_id.to_s) : ""
super
else
replace_param_value(super, @value, test_uploaded_file)
end
end end
protected def to_query_string
@value.nil? ? set("") : set(digest_value)
super
end
def test_uploaded_file def test_uploaded_file
return "" if @original_value.blank?
case Webrat.configuration.mode case Webrat.configuration.mode
when :rails when :rails
if content_type if content_type
ActionController::TestUploadedFile.new(@value, content_type) ActionController::TestUploadedFile.new(@original_value, content_type)
else else
ActionController::TestUploadedFile.new(@value) ActionController::TestUploadedFile.new(@original_value)
end end
when :merb when :rack, :merb
# TODO: support content_type Rack::Test::UploadedFile.new(@original_value, content_type)
File.new(@value)
when :rack
Rack::Test::UploadedFile.new(@value, content_type)
end end
end end
@ -381,31 +370,69 @@ module Webrat
class ResetField < Field #:nodoc: class ResetField < Field #:nodoc:
def self.xpath_search def self.xpath_search
".//input[@type = 'reset']" [".//input[@type = 'reset']"]
end end
end end
class SelectField < Field #:nodoc: class SelectField < Field #:nodoc:
def self.xpath_search def self.xpath_search
".//select" [".//select[not(@multiple)]"]
end end
def options def options
@options ||= SelectOption.load_all(@session, @element) @options ||= SelectOption.load_all(@session, @element)
end end
def unset(value)
@value = nil
end
protected protected
def default_value def default_value
selected_options = Webrat::XML.xpath_search(@element, ".//option[@selected = 'selected']") selected_options = @element.xpath(".//option[@selected = 'selected']")
selected_options = Webrat::XML.xpath_search(@element, ".//option[position() = 1]") if selected_options.empty? selected_options = @element.xpath(".//option[position() = 1]") if selected_options.empty?
selected_options.map do |option| selected_options.map do |option|
return "" if option.nil? return "" if option.nil?
Webrat::XML.attribute(option, "value") || Webrat::XML.inner_html(option) option["value"] || option.inner_html
end.uniq.first
end
end
class MultipleSelectField < Field #:nodoc:
def self.xpath_search
[".//select[@multiple='multiple']"]
end
def options
@options ||= SelectOption.load_all(@session, @element)
end
def set(value)
@value << value
end
def unset(value)
@value.delete(value)
end
protected
# Overwrite SelectField definition because we don't want to select the first option
# (mutliples don't select the first option unlike their non multiple versions)
def default_value
selected_options = @element.xpath(".//option[@selected = 'selected']")
selected_options.map do |option|
return "" if option.nil?
option["value"] || option.inner_html
end.uniq end.uniq
end end
end end
end end

View File

@ -9,7 +9,7 @@ module Webrat
attr_reader :element attr_reader :element
def self.xpath_search def self.xpath_search
".//form" [".//form"]
end end
def fields def fields
@ -27,7 +27,7 @@ module Webrat
protected protected
def dom def dom
Webrat::XML.xpath_at(@session.dom, path) @session.dom.xpath(path).first
end end
def fields_by_type(field_types) def fields_by_type(field_types)
@ -38,66 +38,90 @@ module Webrat
end end
end end
# iterate over all form fields to build a request querystring to get params from it,
# for file_field we made a work around to pass a digest as value to later replace it
# in params hash with the real file.
def params def params
all_params = {} query_string = []
replaces = {}
fields.each do |field| fields.each do |field|
next if field.to_param.nil? next if field.to_query_string.nil?
merge(all_params, field.to_param) replaces.merge!({field.digest_value => field.test_uploaded_file}) if field.is_a?(FileField)
query_string << field.to_query_string
end end
all_params query_params = self.class.query_string_to_params(query_string.join('&'))
query_params = self.class.replace_params_values(query_params, replaces)
self.class.unescape_params(query_params)
end end
def form_method def form_method
Webrat::XML.attribute(@element, "method").blank? ? :get : Webrat::XML.attribute(@element, "method").downcase @element["method"].blank? ? :get : @element["method"].downcase
end end
def form_action def form_action
Webrat::XML.attribute(@element, "action").blank? ? @session.current_url : Webrat::XML.attribute(@element, "action") @element["action"].blank? ? @session.current_url : @element["action"]
end end
def merge(all_params, new_param) def self.replace_param_value(params, oval, nval)
new_param.each do |key, value| output = Hash.new
case all_params[key] params.each do |key, value|
when *hash_classes case value
merge_hash_values(all_params[key], value) when Hash
value = replace_param_value(value, oval, nval)
when Array when Array
all_params[key] += value value = value.map { |o| o == oval ? nval : ( o.is_a?(Hash) ? replace_param_value(o, oval, nval) : o) }
else when oval
all_params[key] = value value = nval
end end
output[key] = value
end
output
end
def self.replace_params_values(params, values)
values.each do |key, value|
params = replace_param_value(params, key, value)
end
params
end
def self.unescape_params(params)
case params.class.name
when 'Hash', 'Mash'
params.each { |key,value| params[key] = unescape_params(value) }
params
when 'Array'
params.collect { |value| unescape_params(value) }
else
params.is_a?(String) ? CGI.unescapeHTML(params) : params
end end
end end
def merge_hash_values(a, b) # :nodoc: def self.query_string_to_params(query_string)
a.keys.each do |k|
if b.has_key?(k)
case [a[k], b[k]].map{|value| value.class}
when *hash_classes.zip(hash_classes)
a[k] = merge_hash_values(a[k], b[k])
b.delete(k)
when [Array, Array]
a[k] += b[k]
b.delete(k)
end
end
end
a.merge!(b)
end
def hash_classes
klasses = [Hash]
case Webrat.configuration.mode case Webrat.configuration.mode
when :rails when :rails
klasses << HashWithIndifferentAccess parse_rails_request_params(query_string)
when :merb when :merb
klasses << Mash ::Merb::Parse.query(query_string)
when :rack, :sinatra
Rack::Utils.parse_nested_query(query_string)
else
Hash[query_string.split('&').map {|query| [ query.split('=').first, query.split('=').last ]}]
end end
klasses
end end
def self.parse_rails_request_params(query_string)
if defined?(ActionController::AbstractRequest)
ActionController::AbstractRequest.parse_query_parameters(query_string)
elsif defined?(ActionController::UrlEncodedPairParser)
ActionController::UrlEncodedPairParser.parse_query_parameters(query_string)
else
Rack::Utils.parse_nested_query(query_string)
end
end
end end
end end

View File

@ -6,11 +6,11 @@ module Webrat
attr_reader :element attr_reader :element
def self.xpath_search def self.xpath_search
".//label" [".//label"]
end end
def for_id def for_id
Webrat::XML.attribute(@element, "for") @element["for"]
end end
def field def field
@ -21,9 +21,9 @@ module Webrat
def field_element def field_element
if for_id.blank? if for_id.blank?
Webrat::XML.xpath_at(@element, *Field.xpath_search_excluding_hidden) @element.xpath(*Field.xpath_search_excluding_hidden).first
else else
Webrat::XML.css_search(@session.current_dom, "#" + for_id).first @session.current_dom.css("#" + for_id).first
end end
end end

View File

@ -7,7 +7,7 @@ module Webrat
class Link < Element #:nodoc: class Link < Element #:nodoc:
def self.xpath_search def self.xpath_search
".//a[@href]" [".//a[@href]"]
end end
def click(options = {}) def click(options = {})
@ -26,7 +26,7 @@ module Webrat
protected protected
def id def id
Webrat::XML.attribute(@element, "id") @element["id"]
end end
def data def data
@ -34,11 +34,11 @@ module Webrat
end end
def title def title
Webrat::XML.attribute(@element, "title") @element["title"]
end end
def href def href
Webrat::XML.attribute(@element, "href") @element["href"]
end end
def absolute_href def absolute_href
@ -53,12 +53,12 @@ module Webrat
def authenticity_token def authenticity_token
return unless onclick && onclick.include?("s.setAttribute('name', 'authenticity_token');") && return unless onclick && onclick.include?("s.setAttribute('name', 'authenticity_token');") &&
onclick =~ /s\.setAttribute\('value', '([a-f0-9]{40})'\);/ ( onclick =~ /s\.setAttribute\('value', '([a-f0-9]{40})'\);/ || onclick =~ /s\.setAttribute\('value', '(.{44})'\);/ )
$LAST_MATCH_INFO.captures.first $LAST_MATCH_INFO.captures.first
end end
def onclick def onclick
Webrat::XML.attribute(@element, "onclick") @element["onclick"]
end end
def http_method def http_method

View File

@ -4,7 +4,7 @@ module Webrat
class SelectOption < Element #:nodoc: class SelectOption < Element #:nodoc:
def self.xpath_search def self.xpath_search
".//option" [".//option"]
end end
def choose def choose
@ -12,6 +12,15 @@ module Webrat
select.set(value) select.set(value)
end end
def unchoose
select.raise_error_if_disabled
select.unset(value)
end
def inner_text
@element.inner_text
end
protected protected
def select def select
@ -28,7 +37,11 @@ module Webrat
end end
def value def value
Webrat::XML.attribute(@element, "value") || Webrat::XML.inner_html(@element) @element["value"] || @element.inner_html
end
def label
@element.inner_html
end end
end end

View File

@ -13,7 +13,7 @@ module Webrat
module Locators module Locators
def field_by_xpath(xpath) def field_by_xpath(xpath)
Field.load(@session, Webrat::XML.xpath_at(dom, xpath)) Field.load(@session, dom.xpath(xpath).first)
end end
end end

View File

@ -11,8 +11,8 @@ module Webrat
def area_element def area_element
area_elements.detect do |area_element| area_elements.detect do |area_element|
Webrat::XML.attribute(area_element, "title") =~ matcher || area_element["title"] =~ matcher ||
Webrat::XML.attribute(area_element, "id") =~ matcher area_element["id"] =~ matcher
end end
end end
@ -21,7 +21,7 @@ module Webrat
end end
def area_elements def area_elements
Webrat::XML.xpath_search(@dom, Area.xpath_search) @dom.xpath(*Area.xpath_search)
end end
def error_message def error_message

View File

@ -20,24 +20,24 @@ module Webrat
end end
def matches_id?(element) def matches_id?(element)
(@value.is_a?(Regexp) && Webrat::XML.attribute(element, "id") =~ @value) || (@value.is_a?(Regexp) && element["id"] =~ @value) ||
(!@value.is_a?(Regexp) && Webrat::XML.attribute(element, "id") == @value.to_s) (!@value.is_a?(Regexp) && element["id"] == @value.to_s)
end end
def matches_value?(element) def matches_value?(element)
Webrat::XML.attribute(element, "value") =~ /^\W*#{Regexp.escape(@value.to_s)}/i element["value"] =~ /^\W*#{Regexp.escape(@value.to_s)}/i
end end
def matches_html?(element) def matches_html?(element)
Webrat::XML.inner_html(element) =~ /#{Regexp.escape(@value.to_s)}/i element.inner_html =~ /#{Regexp.escape(@value.to_s)}/i
end end
def matches_alt?(element) def matches_alt?(element)
Webrat::XML.attribute(element, "alt") =~ /^\W*#{Regexp.escape(@value.to_s)}/i element["alt"] =~ /^\W*#{Regexp.escape(@value.to_s)}/i
end end
def button_elements def button_elements
Webrat::XML.xpath_search(@dom, *ButtonField.xpath_search) @dom.xpath(*ButtonField.xpath_search)
end end
def error_message def error_message

View File

@ -12,15 +12,15 @@ module Webrat
def field_element def field_element
field_elements.detect do |field_element| field_elements.detect do |field_element|
if @value.is_a?(Regexp) if @value.is_a?(Regexp)
Webrat::XML.attribute(field_element, "id") =~ @value field_element["id"] =~ @value
else else
Webrat::XML.attribute(field_element, "id") == @value.to_s field_element["id"] == @value.to_s
end end
end end
end end
def field_elements def field_elements
Webrat::XML.xpath_search(@dom, *Field.xpath_search) @dom.xpath(*Field.xpath_search)
end end
def error_message def error_message

View File

@ -25,7 +25,7 @@ module Webrat
end end
def label_elements def label_elements
Webrat::XML.xpath_search(@dom, Label.xpath_search) @dom.xpath(*Label.xpath_search)
end end
def error_message def error_message
@ -33,7 +33,7 @@ module Webrat
end end
def text(element) def text(element)
str = Webrat::XML.all_inner_text(element) str = element.inner_text
str.gsub!("\n","") str.gsub!("\n","")
str.strip! str.strip!
str.squeeze!(" ") str.squeeze!(" ")

View File

@ -11,19 +11,19 @@ module Webrat
def field_element def field_element
field_elements.detect do |field_element| field_elements.detect do |field_element|
Webrat::XML.attribute(field_element, "name") == @value.to_s field_element["name"] == @value.to_s
end end
end end
def field_elements def field_elements
Webrat::XML.xpath_search(@dom, *xpath_searches) @dom.xpath(*xpath_searches)
end end
def xpath_searches def xpath_searches
if @field_types.any? if @field_types.any?
@field_types.map { |field_type| field_type.xpath_search }.flatten @field_types.map { |field_type| field_type.xpath_search }.flatten
else else
Array(Field.xpath_search) Field.xpath_search
end end
end end

View File

@ -10,7 +10,7 @@ module Webrat
end end
def form_element def form_element
Webrat::XML.css_at(@dom, "#" + @value) @dom.css("#" + @value).first || @dom.css(@value).first
end end
end end

View File

@ -17,11 +17,11 @@ module Webrat
end end
def label_elements def label_elements
Webrat::XML.xpath_search(@dom, Label.xpath_search) @dom.xpath(*Label.xpath_search)
end end
def text(label_element) def text(label_element)
str = Webrat::XML.all_inner_text(label_element) str = label_element.inner_text
str.gsub!("\n","") str.gsub!("\n","")
str.strip! str.strip!
str.squeeze!(" ") str.squeeze!(" ")

View File

@ -10,7 +10,7 @@ module Webrat
end end
def link_element def link_element
matching_links.min { |a, b| Webrat::XML.all_inner_text(a).length <=> Webrat::XML.all_inner_text(b).length } matching_links.min { |a, b| a.inner_text.length <=> b.inner_text.length }
end end
def matching_links def matching_links
@ -27,21 +27,21 @@ module Webrat
matcher = /#{Regexp.escape(@value.to_s)}/i matcher = /#{Regexp.escape(@value.to_s)}/i
end end
replace_nbsp(Webrat::XML.all_inner_text(link)) =~ matcher || replace_nbsp(link.inner_text) =~ matcher ||
replace_nbsp_ref(Webrat::XML.inner_html(link)) =~ matcher || replace_nbsp_ref(link.inner_html) =~ matcher ||
Webrat::XML.attribute(link, "title")=~ matcher link["title"] =~ matcher
end end
def matches_id?(link) def matches_id?(link)
if @value.is_a?(Regexp) if @value.is_a?(Regexp)
(Webrat::XML.attribute(link, "id") =~ @value) ? true : false link["id"] =~ @value ? true : false
else else
(Webrat::XML.attribute(link, "id") == @value) ? true : false link["id"] == @value ? true : false
end end
end end
def link_elements def link_elements
Webrat::XML.xpath_search(@dom, *Link.xpath_search) @dom.xpath(*Link.xpath_search)
end end
def replace_nbsp(str) def replace_nbsp(str)

View File

@ -19,17 +19,17 @@ module Webrat
field.options.detect do |o| field.options.detect do |o|
if @option_text.is_a?(Regexp) if @option_text.is_a?(Regexp)
Webrat::XML.inner_html(o.element) =~ @option_text o.element.inner_text =~ @option_text
else else
Webrat::XML.inner_html(o.element) == @option_text.to_s o.inner_text == @option_text.to_s
end end
end end
else else
option_element = option_elements.detect do |o| option_element = option_elements.detect do |o|
if @option_text.is_a?(Regexp) if @option_text.is_a?(Regexp)
Webrat::XML.inner_html(o) =~ @option_text o.inner_text =~ @option_text
else else
Webrat::XML.inner_html(o) == @option_text.to_s o.inner_text == @option_text.to_s
end end
end end
@ -38,7 +38,7 @@ module Webrat
end end
def option_elements def option_elements
Webrat::XML.xpath_search(@dom, *SelectOption.xpath_search) @dom.xpath(*SelectOption.xpath_search)
end end
def error_message def error_message

View File

@ -1,3 +1,5 @@
require "logger"
module Webrat module Webrat
module Logging #:nodoc: module Logging #:nodoc:
@ -11,12 +13,9 @@ module Webrat
when :rails when :rails
defined?(RAILS_DEFAULT_LOGGER) ? RAILS_DEFAULT_LOGGER : nil defined?(RAILS_DEFAULT_LOGGER) ? RAILS_DEFAULT_LOGGER : nil
when :merb when :merb
Merb.logger ::Merb.logger
else else
@logger ||= begin @logger ||= ::Logger.new("webrat.log")
require "logger"
::Logger.new("webrat.log")
end
end end
end end

View File

@ -7,17 +7,12 @@ module Webrat
end end
def matches?(stringlike) def matches?(stringlike)
if Webrat.configuration.parse_with_nokogiri? @document = Webrat::XML.document(stringlike)
@document = Webrat.nokogiri_document(stringlike) @element = @document.inner_text
else
@document = Webrat.hpricot_document(stringlike)
end
@element = Webrat::XML.inner_text(@document)
case @content case @content
when String when String
@element.include?(@content) @element.gsub(/\s+/, ' ').include?(@content)
when Regexp when Regexp
@element.match(@content) @element.match(@content)
end end

View File

@ -1,5 +1,4 @@
require "webrat/core/xml/nokogiri" require "webrat/core/xml"
require "webrat/core/xml/rexml"
module Webrat module Webrat
module Matchers module Matchers
@ -15,39 +14,17 @@ module Webrat
@block ||= block @block ||= block
matched = matches(stringlike) matched = matches(stringlike)
@block.call(matched) if @block
if @options[:count] if @options[:count]
matched.size == @options[:count] && (!@block || @block.call(matched)) matched.size == @options[:count].to_i
else else
matched.any? && (!@block || @block.call(matched)) matched.any?
end end
end end
def matches(stringlike) def matches(stringlike)
if Webrat.configuration.parse_with_nokogiri? nokogiri_matches(stringlike)
nokogiri_matches(stringlike)
else
rexml_matches(stringlike)
end
end
def rexml_matches(stringlike)
if REXML::Node === stringlike || Array === stringlike
@query = query.map { |q| q.gsub(%r'^//', './/') }
else
@query = query
end
add_options_conditions_to(@query)
@document = Webrat.rexml_document(stringlike)
@query.map do |q|
if @document.is_a?(Array)
@document.map { |d| REXML::XPath.match(d, q) }
else
REXML::XPath.match(@document, q)
end
end.flatten.compact
end end
def nokogiri_matches(stringlike) def nokogiri_matches(stringlike)

View File

@ -3,7 +3,7 @@ module Webrat
def self.delegate_to_session(*meths) def self.delegate_to_session(*meths)
meths.each do |meth| meths.each do |meth|
self.class_eval <<-RUBY self.class_eval(<<-RUBY, __FILE__, __LINE__)
def #{meth}(*args, &blk) def #{meth}(*args, &blk)
webrat_session.#{meth}(*args, &blk) webrat_session.#{meth}(*args, &blk)
end end
@ -39,6 +39,7 @@ module Webrat
:unchecks, :uncheck, :unchecks, :uncheck,
:chooses, :choose, :chooses, :choose,
:selects, :select, :selects, :select,
:unselects, :unselect,
:attaches_file, :attach_file, :attaches_file, :attach_file,
:current_page, :current_page,
:current_url, :current_url,

View File

@ -8,8 +8,8 @@ module Webrat #:nodoc:
def mime_type(type) def mime_type(type)
return type if type.nil? || type.to_s.include?("/") return type if type.nil? || type.to_s.include?("/")
type = ".#{type}" unless type.to_s[0] == ?. type = ".#{type}" unless type.to_s[0] == ?.
MIME_TYPES.fetch(type) { |type| MIME_TYPES.fetch(type) { |invalid_type|
raise ArgumentError.new("Invalid Mime type: #{type}") raise ArgumentError.new("Invalid Mime type: #{invalid_type}")
} }
end end

View File

@ -6,12 +6,12 @@ module Webrat
# Example: # Example:
# save_and_open_page # save_and_open_page
def save_and_open_page def save_and_open_page
return unless File.exist?(saved_page_dir) return unless File.exist?(Webrat.configuration.saved_pages_dir)
filename = "#{saved_page_dir}/webrat-#{Time.now.to_i}.html" filename = "#{Webrat.configuration.saved_pages_dir}/webrat-#{Time.now.to_i}.html"
File.open(filename, "w") do |f| File.open(filename, "w") do |f|
f.write rewrite_css_and_image_references(response_body) f.write response_body
end end
open_in_browser(filename) open_in_browser(filename)
@ -24,25 +24,5 @@ module Webrat
warn "Sorry, you need to install launchy to open pages: `gem install launchy`" warn "Sorry, you need to install launchy to open pages: `gem install launchy`"
end end
def rewrite_css_and_image_references(response_html) # :nodoc:
return response_html unless doc_root
response_html.gsub(/("|')\/(stylesheets|images)/, '\1' + doc_root + '/\2')
end
def saved_page_dir #:nodoc:
File.expand_path(".")
end
def doc_root #:nodoc:
nil
end
private
# accessor for testing
def ruby_platform
RUBY_PLATFORM
end
end end
end end

View File

@ -28,6 +28,7 @@ module Webrat
attr_reader :session attr_reader :session
def initialize(session, &block) #:nodoc: def initialize(session, &block) #:nodoc:
@selector, @dom = nil
@session = session @session = session
instance_eval(&block) if block_given? instance_eval(&block) if block_given?
@ -112,6 +113,21 @@ module Webrat
webrat_deprecate :selects, :select webrat_deprecate :selects, :select
# Verifies that a an option element exists on the current page with the specified
# text. You can optionally restrict the search to a specific select list by
# assigning <tt>options[:from]</tt> the value of the select list's name or
# a label. Remove the option's value before the form is submitted.
#
# Examples:
# unselect "January"
# unselect "February", :from => "event_month"
# unselect "February", :from => "Event Month"
def unselect(option_text, options={})
select_option(option_text, options[:from]).unchoose
end
webrat_deprecate :unselects, :unselect
DATE_TIME_SUFFIXES = { DATE_TIME_SUFFIXES = {
:year => '1i', :year => '1i',
:month => '2i', :month => '2i',
@ -312,12 +328,12 @@ module Webrat
dom = Webrat::XML.html_document(@response_body) dom = Webrat::XML.html_document(@response_body)
end end
Webrat.define_dom_method(@response, dom) Webrat::XML.define_dom_method(@response, dom)
return dom return dom
end end
def scoped_dom def scoped_dom
Webrat::XML.css_at(@scope.dom, @selector) @scope.dom.css(@selector).first
end end
def locate_field(field_locator, *field_types) #:nodoc: def locate_field(field_locator, *field_types) #:nodoc:

View File

@ -65,7 +65,7 @@ For example:
attr_reader :current_url attr_reader :current_url
attr_reader :elements attr_reader :elements
def_delegators :@adapter, :response, :response_code, :response_body, def_delegators :@adapter, :response, :response_code, :response_body, :response_headers,
:response_body=, :response_code=, :response_body=, :response_code=,
:get, :post, :put, :delete :get, :post, :put, :delete
@ -75,6 +75,7 @@ For example:
@data = {} @data = {}
@default_headers = {} @default_headers = {}
@custom_headers = {} @custom_headers = {}
@current_url = nil
reset reset
end end
@ -92,10 +93,6 @@ For example:
page page
end end
def doc_root #:nodoc:
nil
end
def header(key, value) def header(key, value)
@custom_headers[key] = value @custom_headers[key] = value
end end
@ -105,7 +102,7 @@ For example:
end end
def basic_auth(user, pass) def basic_auth(user, pass)
encoded_login = ["#{user}:#{pass}"].pack("m*") encoded_login = ["#{user}:#{pass}"].pack("m*").gsub(/\n/, '')
header('HTTP_AUTHORIZATION', "Basic #{encoded_login}") header('HTTP_AUTHORIZATION', "Basic #{encoded_login}")
end end
@ -159,7 +156,7 @@ For example:
end end
def redirect? #:nodoc: def redirect? #:nodoc:
(response_code / 100).to_i == 3 [301, 302, 303, 307].include?(response_code)
end end
def internal_redirect? def internal_redirect?
@ -260,6 +257,7 @@ For example:
def_delegators :current_scope, :uncheck, :unchecks def_delegators :current_scope, :uncheck, :unchecks
def_delegators :current_scope, :choose, :chooses def_delegators :current_scope, :choose, :chooses
def_delegators :current_scope, :select, :selects def_delegators :current_scope, :select, :selects
def_delegators :current_scope, :unselect, :unselects
def_delegators :current_scope, :select_datetime, :selects_datetime def_delegators :current_scope, :select_datetime, :selects_datetime
def_delegators :current_scope, :select_date, :selects_date def_delegators :current_scope, :select_date, :selects_date
def_delegators :current_scope, :select_time, :selects_time def_delegators :current_scope, :select_time, :selects_time
@ -284,7 +282,7 @@ For example:
end end
def response_location def response_location
response.headers["Location"] response_headers['Location']
end end
def current_host def current_host

View File

@ -1,115 +1,72 @@
require "webrat/core/xml/nokogiri" require "webrat/core_extensions/meta_class"
require "webrat/core/xml/hpricot"
require "webrat/core/xml/rexml"
module Webrat #:nodoc: module Webrat #:nodoc:
module XML #:nodoc: module XML #:nodoc:
def self.document(stringlike) #:nodoc: def self.document(stringlike) #:nodoc:
if Webrat.configuration.parse_with_nokogiri? return stringlike.dom if stringlike.respond_to?(:dom)
Webrat.nokogiri_document(stringlike)
if Nokogiri::HTML::Document === stringlike
stringlike
elsif Nokogiri::XML::NodeSet === stringlike
stringlike
elsif stringlike.respond_to?(:body)
Nokogiri::HTML(stringlike.body.to_s)
else else
Webrat.rexml_document(Webrat.hpricot_document(stringlike).to_html) Nokogiri::HTML(stringlike.to_s)
end end
end end
def self.html_document(stringlike) #:nodoc: def self.html_document(stringlike) #:nodoc:
if Webrat.configuration.parse_with_nokogiri? return stringlike.dom if stringlike.respond_to?(:dom)
Webrat.html_nokogiri_document(stringlike)
if Nokogiri::HTML::Document === stringlike
stringlike
elsif Nokogiri::XML::NodeSet === stringlike
stringlike
elsif stringlike.respond_to?(:body)
Nokogiri::HTML(stringlike.body.to_s)
else else
Webrat.rexml_document(Webrat.hpricot_document(stringlike).to_html) Nokogiri::HTML(stringlike.to_s)
end end
end end
def self.xml_document(stringlike) #:nodoc: def self.xml_document(stringlike) #:nodoc:
if Webrat.configuration.parse_with_nokogiri? return stringlike.dom if stringlike.respond_to?(:dom)
Webrat.xml_nokogiri_document(stringlike)
if Nokogiri::HTML::Document === stringlike
stringlike
elsif Nokogiri::XML::NodeSet === stringlike
stringlike
elsif stringlike.respond_to?(:body)
Nokogiri::XML(stringlike.body.to_s)
else else
Webrat.rexml_document(Webrat.hpricot_document(stringlike).to_html) Nokogiri::XML(stringlike.to_s)
end end
end end
def self.to_html(element) def self.define_dom_method(object, dom) #:nodoc:
if Webrat.configuration.parse_with_nokogiri? object.meta_class.send(:define_method, :dom) do
element.to_html dom
else
element.to_s
end end
end end
def self.inner_html(element)
if Webrat.configuration.parse_with_nokogiri?
element.inner_html
else
element.text
end
end
def self.all_inner_text(element)
if Webrat.configuration.parse_with_nokogiri?
element.inner_text
else
Hpricot(element.to_s).children.first.inner_text
end
end
def self.inner_text(element)
if Webrat.configuration.parse_with_nokogiri?
element.inner_text
else
if defined?(Hpricot::Doc) && element.is_a?(Hpricot::Doc)
element.inner_text
else
element.text
end
end
end
def self.xpath_to(element)
if Webrat.configuration.parse_with_nokogiri?
element.path
else
element.xpath
end
end
def self.attribute(element, attribute_name)
return element[attribute_name] if element.is_a?(Hash)
if Webrat.configuration.parse_with_nokogiri?
element[attribute_name]
else
element.attributes[attribute_name]
end
end
def self.xpath_at(*args)
xpath_search(*args).first
end
def self.css_at(*args)
css_search(*args).first
end
def self.xpath_search(element, *searches)
searches.flatten.map do |search|
if Webrat.configuration.parse_with_nokogiri?
element.xpath(search)
else
REXML::XPath.match(element, search)
end
end.flatten.compact
end
def self.css_search(element, *searches) #:nodoc:
xpath_search(element, css_to_xpath(*searches))
end
def self.css_to_xpath(*selectors)
selectors.map do |rule|
Nokogiri::CSS.xpath_for(rule, :prefix => ".//")
end.flatten.uniq
end
end end
end end
module Nokogiri #:nodoc:
module CSS #:nodoc:
class XPathVisitor #:nodoc:
def visit_pseudo_class_text(node) #:nodoc:
"@type='text'"
end
def visit_pseudo_class_password(node) #:nodoc:
"@type='password'"
end
end
end
end

View File

@ -1,19 +0,0 @@
module Webrat
def self.hpricot_document(stringlike)
return stringlike.dom if stringlike.respond_to?(:dom)
if Hpricot::Doc === stringlike
stringlike
elsif Hpricot::Elements === stringlike
stringlike
elsif StringIO === stringlike
Hpricot(stringlike.string)
elsif stringlike.respond_to?(:body)
Hpricot(stringlike.body.to_s)
else
Hpricot(stringlike.to_s)
end
end
end

View File

@ -1,76 +0,0 @@
require "webrat/core_extensions/meta_class"
module Webrat
def self.nokogiri_document(stringlike) #:nodoc:
return stringlike.dom if stringlike.respond_to?(:dom)
if Nokogiri::HTML::Document === stringlike
stringlike
elsif Nokogiri::XML::NodeSet === stringlike
stringlike
elsif StringIO === stringlike
Nokogiri::HTML(stringlike.string)
elsif stringlike.respond_to?(:body)
Nokogiri::HTML(stringlike.body.to_s)
else
Nokogiri::HTML(stringlike.to_s)
end
end
def self.html_nokogiri_document(stringlike) #:nodoc:
return stringlike.dom if stringlike.respond_to?(:dom)
if Nokogiri::HTML::Document === stringlike
stringlike
elsif Nokogiri::XML::NodeSet === stringlike
stringlike
elsif StringIO === stringlike
Nokogiri::HTML(stringlike.string)
elsif stringlike.respond_to?(:body)
Nokogiri::HTML(stringlike.body.to_s)
else
Nokogiri::HTML(stringlike.to_s)
end
end
def self.xml_nokogiri_document(stringlike) #:nodoc:
return stringlike.dom if stringlike.respond_to?(:dom)
if Nokogiri::HTML::Document === stringlike
stringlike
elsif Nokogiri::XML::NodeSet === stringlike
stringlike
elsif StringIO === stringlike
Nokogiri::XML(stringlike.string)
elsif stringlike.respond_to?(:body)
Nokogiri::XML(stringlike.body.to_s)
else
Nokogiri::XML(stringlike.to_s)
end
end
def self.define_dom_method(object, dom) #:nodoc:
object.meta_class.send(:define_method, :dom) do
dom
end
end
end
module Nokogiri #:nodoc:
module CSS #:nodoc:
class XPathVisitor #:nodoc:
def visit_pseudo_class_text(node) #:nodoc:
"@type='text'"
end
def visit_pseudo_class_password(node) #:nodoc:
"@type='password'"
end
end
end
end

View File

@ -1,24 +0,0 @@
module Webrat
def self.rexml_document(stringlike)
stringlike = stringlike.body.to_s if stringlike.respond_to?(:body)
case stringlike
when REXML::Document
stringlike.root
when REXML::Node, Array
stringlike
else
begin
REXML::Document.new(stringlike.to_s).root
rescue REXML::ParseException => e
if e.message.include?("second root element")
REXML::Document.new("<fake-root-element>#{stringlike}</fake-root-element>").root
else
raise e
end
end
end
end
end

View File

@ -1,5 +1,5 @@
class NilClass #:nodoc: class NilClass #:nodoc:
def to_param def to_query_string
nil nil
end end
end end

View File

@ -0,0 +1,10 @@
module Merb #:nodoc:
module Test #:nodoc:
module RequestHelper #:nodoc:
def request(uri, env = {})
@_webrat_session ||= Webrat::MerbAdapter.new
@_webrat_session.response = @_webrat_session.request(uri, env)
end
end
end
end

View File

@ -0,0 +1,25 @@
require "action_controller"
require "action_controller/integration"
module ActionController #:nodoc:
IntegrationTest.class_eval do
include Webrat::Methods
include Webrat::Matchers
# The Rails version of within supports passing in a model and Webrat
# will apply a scope based on Rails' dom_id for that model.
#
# Example:
# within User.last do
# click_link "Delete"
# end
def within(selector_or_object, &block)
if selector_or_object.is_a?(String)
super
else
super('#' + RecordIdentifier.dom_id(selector_or_object), &block)
end
end
end
end

View File

@ -0,0 +1,11 @@
# Supports using the matchers in controller, helper, and view specs if you're
# using rspec-rails. Just add a require statement to spec/spec_helper.rb or env.rb:
#
# require 'webrat/integrations/rspec-rails'
#
require "nokogiri"
require "webrat/core/matchers"
Spec::Runner.configure do |config|
config.include(Webrat::Matchers, :type => [:controller, :helper, :view])
end

View File

@ -0,0 +1,11 @@
require "webrat/selenium"
if defined?(ActionController::IntegrationTest)
module ActionController #:nodoc:
IntegrationTest.class_eval do
include Webrat::Methods
include Webrat::Selenium::Methods
include Webrat::Selenium::Matchers
end
end
end

View File

@ -1,82 +0,0 @@
require "webrat"
require "merb-core"
require "webrat/merb_multipart_support"
module Webrat
class MerbAdapter #:nodoc:
include Merb::Test::MakeRequest
# Include Webrat's own version of multipart_post/put because the officially
# supported methods in Merb don't perform the request correctly.
include MerbMultipartSupport
attr_accessor :response
def initialize(context=nil); end
def get(url, data, headers = nil)
do_request(url, data, headers, "GET")
end
def post(url, data, headers = nil)
do_request(url, data, headers, "POST")
end
def put(url, data, headers = nil)
do_request(url, data, headers, "PUT")
end
def delete(url, data, headers = nil)
do_request(url, data, headers, "DELETE")
end
def response_body
@response.body.to_s
end
def response_code
@response.status
end
def do_request(url, data, headers, method)
if method == "POST" && has_file?(data)
@response = multipart_post(url, data, :headers => headers)
elsif method == "PUT" && has_file?(data)
@response = multipart_put(url, data, :headers => headers)
else
@response = request(url,
:params => (data && data.any?) ? data : nil,
:headers => headers,
:method => method)
end
end
protected
# Recursively search the data for a file attachment.
def has_file?(data)
data.each do |key, value|
if value.is_a?(Hash)
return has_file?(value)
else
return true if value.is_a?(File)
end
end
return false
end
end
end
module Merb #:nodoc:
module Test #:nodoc:
module RequestHelper #:nodoc:
def request(uri, env = {})
@_webrat_session ||= Webrat::MerbAdapter.new
@_webrat_session.response = @_webrat_session.request(uri, env)
end
end
end
end

View File

@ -1,27 +0,0 @@
module Webrat
# These methods are copied from merb-core/two-oh.rb which defines new
# multipart_post and multipart_put methods for Merb::Test::MultipartRequestHelper.
# We can't require two-oh.rb because it alters Merb's own behavior, causing
# failing specs in Merb when Webrat is required.
module MerbMultipartSupport
def multipart_request(path, params = {}, env = {})
multipart = Merb::Test::MultipartRequestHelper::Post.new(params)
body, head = multipart.to_multipart
env["CONTENT_TYPE"] = head
env["CONTENT_LENGTH"] = body.size
env[:input] = StringIO.new(body)
request(path, env)
end
def multipart_post(path, params = {}, env = {})
env[:method] = "POST"
multipart_request(path, params, env)
end
def multipart_put(path, params = {}, env = {}, &block)
env[:method] = "PUT"
multipart_request(path, params, env)
end
end
end

View File

@ -1,10 +1,2 @@
# Supports using the matchers in controller, helper, and view specs if you're warn("Requiring 'webrat/rspec-rails' is deprecated. Please require 'webrat/integrations/rspec-rails' instead")
# using rspec-rails. Just add a require statement to spec/spec_helper.rb or env.rb: require "webrat/integrations/rspec-rails"
#
# require 'webrat/rspec-rails'
#
require "webrat/core/matchers"
Spec::Runner.configure do |config|
config.include(Webrat::Matchers, :type => [:controller, :helper, :view])
end

View File

@ -68,13 +68,3 @@ module Webrat
end end
end end
end end
if defined?(ActionController::IntegrationTest)
module ActionController #:nodoc:
IntegrationTest.class_eval do
include Webrat::Methods
include Webrat::Selenium::Methods
include Webrat::Selenium::Matchers
end
end
end

View File

@ -2,4 +2,4 @@ require "webrat/selenium/application_servers/base"
require "webrat/selenium/application_servers/sinatra" require "webrat/selenium/application_servers/sinatra"
require "webrat/selenium/application_servers/merb" require "webrat/selenium/application_servers/merb"
require "webrat/selenium/application_servers/rails" require "webrat/selenium/application_servers/rails"
require "webrat/selenium/application_servers/external" require "webrat/selenium/application_servers/external"

View File

@ -23,4 +23,4 @@ module Webrat
end end
end end
end end
end end

View File

@ -1,16 +1,48 @@
// Credit to: http://simonwillison.net/2006/Jan/20/escape/
RegExp.escape = function(text) {
if (!arguments.callee.sRE) {
var specials = [
'/', '.', '*', '+', '?', '|',
'(', ')', '[', ']', '{', '}', '\\'
];
arguments.callee.sRE = new RegExp(
'(\\' + specials.join('|\\') + ')', 'g'
);
}
return text.replace(arguments.callee.sRE, '\\$1');
};
var allLabels = inDocument.getElementsByTagName("label"); var allLabels = inDocument.getElementsByTagName("label");
var regExp = new RegExp('^\\W*' + RegExp.escape(locator) + '(\\b|$)', 'i');
var candidateLabels = $A(allLabels).select(function(candidateLabel){ var candidateLabels = $A(allLabels).select(function(candidateLabel){
var regExp = new RegExp('^' + locator + '\\b', 'i');
var labelText = getText(candidateLabel).strip(); var labelText = getText(candidateLabel).strip();
return (labelText.search(regExp) >= 0); return (labelText.search(regExp) >= 0);
}); });
if (candidateLabels.length == 0) { if (candidateLabels.length == 0) {
return null; return null;
} }
candidateLabels = candidateLabels.sortBy(function(s) { return s.length * -1; }); //reverse length sort
//reverse length sort
candidateLabels = candidateLabels.sortBy(function(s) {
return s.length * -1;
});
var locatedLabel = candidateLabels.first(); var locatedLabel = candidateLabels.first();
var labelFor = locatedLabel.getAttribute('for'); var labelFor = null;
if ((labelFor == null) && (locatedLabel.hasChildNodes())) {
return locatedLabel.firstChild; //TODO: should find the first form field, not just any node if (locatedLabel.getAttribute('for')) {
labelFor = locatedLabel.getAttribute('for');
} else if (locatedLabel.attributes['for']) { // IE
labelFor = locatedLabel.attributes['for'].nodeValue;
} }
if ((labelFor == null) && (locatedLabel.hasChildNodes())) {
return locatedLabel.getElementsByTagName('button')[0]
|| locatedLabel.getElementsByTagName('input')[0]
|| locatedLabel.getElementsByTagName('textarea')[0]
|| locatedLabel.getElementsByTagName('select')[0];
}
return selenium.browserbot.locationStrategies['id'].call(this, labelFor, inDocument, inWindow); return selenium.browserbot.locationStrategies['id'].call(this, labelFor, inDocument, inWindow);

View File

@ -1,4 +1,5 @@
var locationStrategies = selenium.browserbot.locationStrategies; var locationStrategies = selenium.browserbot.locationStrategies;
return locationStrategies['id'].call(this, locator, inDocument, inWindow) return locationStrategies['id'].call(this, locator, inDocument, inWindow)
|| locationStrategies['name'].call(this, locator, inDocument, inWindow) || locationStrategies['name'].call(this, locator, inDocument, inWindow)
|| locationStrategies['label'].call(this, locator, inDocument, inWindow) || locationStrategies['label'].call(this, locator, inDocument, inWindow)

View File

@ -1,12 +1,32 @@
var links = inDocument.getElementsByTagName('a'); var links = inDocument.getElementsByTagName('a');
var candidateLinks = $A(links).select(function(candidateLink) { var candidateLinks = $A(links).select(function(candidateLink) {
var textMatched = PatternMatcher.matches(locator, getText(candidateLink)); var textMatched = false;
var idMatched = PatternMatcher.matches(locator, candidateLink.id); var titleMatched = false;
var titleMatched = PatternMatcher.matches(locator, candidateLink.title); var idMatched = false;
if (getText(candidateLink).toLowerCase().indexOf(locator.toLowerCase()) != -1) {
textMatched = true;
}
if (candidateLink.title.toLowerCase().indexOf(locator.toLowerCase()) != -1) {
titleMatched = true;
}
if (candidateLink.id.toLowerCase().indexOf(locator.toLowerCase()) != -1) {
idMatched = true;
}
return textMatched || idMatched || titleMatched; return textMatched || idMatched || titleMatched;
}); });
if (candidateLinks.length == 0) { if (candidateLinks.length == 0) {
return null; return null;
} }
candidateLinks = candidateLinks.sortBy(function(s) { return s.length * -1; }); //reverse length sort
//reverse length sort
candidateLinks = candidateLinks.sortBy(function(s) {
return s.length * -1;
});
return candidateLinks.first(); return candidateLinks.first();

View File

@ -7,29 +7,33 @@ module Webrat
end end
def matches?(response) def matches?(response)
if @content.is_a?(Regexp)
text_finder = "regexp:#{@content.source}"
else
text_finder = @content
end
response.session.wait_for do response.session.wait_for do
response.selenium.is_text_present(text_finder) response.selenium.is_text_present(text_finder)
end end
rescue Webrat::TimeoutError rescue Webrat::TimeoutError => e
false @error_message = e.message
false
end
def does_not_match?(response)
response.session.wait_for do
!response.selenium.is_text_present(text_finder)
end
rescue Webrat::TimeoutError => e
@error_message = e.message
false
end end
# ==== Returns # ==== Returns
# String:: The failure message. # String:: The failure message.
def failure_message def failure_message
"expected the following element's content to #{content_message}:\n#{@element}" "expected the response to #{content_message}:\n#{@error_message}"
end end
# ==== Returns # ==== Returns
# String:: The failure message to be displayed in negative matches. # String:: The failure message to be displayed in negative matches.
def negative_failure_message def negative_failure_message
"expected the following element's content to not #{content_message}:\n#{@element}" "expected the response to not #{content_message}"
end end
def content_message def content_message
@ -40,6 +44,14 @@ module Webrat
"match #{@content.inspect}" "match #{@content.inspect}"
end end
end end
def text_finder
if @content.is_a?(Regexp)
"regexp:#{@content.source}"
else
@content
end
end
end end
# Matches the contents of an HTML document with # Matches the contents of an HTML document with
@ -52,7 +64,7 @@ module Webrat
# the supplied string or regexp # the supplied string or regexp
def assert_contain(content) def assert_contain(content)
hc = HasContent.new(content) hc = HasContent.new(content)
assert hc.matches?(response), hc.failure_message assert hc.matches?(response), hc.failure_message
end end
# Asserts that the body of the response # Asserts that the body of the response

View File

@ -14,6 +14,14 @@ module Webrat
false false
end end
def does_not_match?(response)
response.session.wait_for do
!response.selenium.is_element_present("css=#{@expected}")
end
rescue Webrat::TimeoutError
false
end
# ==== Returns # ==== Returns
# String:: The failure message. # String:: The failure message.
def failure_message def failure_message

View File

@ -14,6 +14,14 @@ module Webrat
false false
end end
def does_not_match?(response)
response.session.wait_for do
!response.selenium.is_element_present("xpath=#{@expected}")
end
rescue Webrat::TimeoutError
false
end
# ==== Returns # ==== Returns
# String:: The failure message. # String:: The failure message.
def failure_message def failure_message

View File

@ -31,10 +31,13 @@ module Webrat
def remote_control def remote_control
return @remote_control if @remote_control return @remote_control if @remote_control
server_options = { :timeout => Webrat.configuration.selenium_browser_startup_timeout }
server_options[:firefox_profile] = Webrat.configuration.selenium_firefox_profile if Webrat.configuration.selenium_firefox_profile
@remote_control = ::Selenium::RemoteControl::RemoteControl.new("0.0.0.0", @remote_control = ::Selenium::RemoteControl::RemoteControl.new("0.0.0.0",
Webrat.configuration.selenium_server_port, Webrat.configuration.selenium_server_port,
:timeout => Webrat.configuration.selenium_browser_startup_timeout) server_options)
@remote_control.jar_file = jar_path @remote_control.jar_file = jar_path
return @remote_control return @remote_control
@ -61,7 +64,7 @@ module Webrat
TCPSocket.wait_for_service_with_timeout \ TCPSocket.wait_for_service_with_timeout \
:host => (Webrat.configuration.selenium_server_address || "0.0.0.0"), :host => (Webrat.configuration.selenium_server_address || "0.0.0.0"),
:port => Webrat.configuration.selenium_server_port, :port => Webrat.configuration.selenium_server_port,
:timeout => 15 # seconds :timeout => 45 # seconds
end end
end end
@ -74,8 +77,8 @@ module Webrat
def stop def stop
silence_stream(STDOUT) do silence_stream(STDOUT) do
::Selenium::RemoteControl::RemoteControl.new("0.0.0.0", ::Selenium::RemoteControl::RemoteControl.new("0.0.0.0",
Webrat.configuration.selenium_server_port, Webrat.configuration.selenium_server_port,
:timeout => 5).stop :timeout => 5).stop
end end
end end

View File

@ -3,6 +3,13 @@ require "webrat/selenium/selenium_rc_server"
require "webrat/selenium/application_server_factory" require "webrat/selenium/application_server_factory"
require "webrat/selenium/application_servers/base" require "webrat/selenium/application_servers/base"
begin
require "selenium"
rescue LoadError => e
e.message << " (You may need to install the selenium-rc gem)"
raise e
end
module Webrat module Webrat
class TimeoutError < WebratError class TimeoutError < WebratError
end end
@ -77,7 +84,12 @@ module Webrat
webrat_deprecate :clicks_button, :click_button webrat_deprecate :clicks_button, :click_button
def click_link(link_text_or_regexp, options = {}) def click_link(link_text_or_regexp, options = {})
pattern = adjust_if_regexp(link_text_or_regexp) if link_text_or_regexp.is_a?(Regexp)
pattern = "evalregex:#{link_text_or_regexp.inspect}"
else
pattern = link_text_or_regexp.to_s
end
locator = "webratlink=#{pattern}" locator = "webratlink=#{pattern}"
selenium.wait_for_element locator, :timeout_in_seconds => 5 selenium.wait_for_element locator, :timeout_in_seconds => 5
selenium.click locator selenium.click locator
@ -162,7 +174,19 @@ module Webrat
sleep 0.25 sleep 0.25
end end
raise Webrat::TimeoutError.new(message + " (after #{timeout} sec)") error_message = "#{message} (after #{timeout} sec)"
if $browser && Webrat.configuration.selenium_verbose_output
error_message += <<-EOS
HTML of the page was:
#{selenium.get_html_source}"
EOS
end
raise Webrat::TimeoutError.new(error_message)
true true
end end
@ -176,9 +200,9 @@ module Webrat
def save_and_open_screengrab def save_and_open_screengrab
return unless File.exist?(saved_page_dir) return unless File.exist?(Webrat.configuration.saved_pages_dir)
filename = "#{saved_page_dir}/webrat-#{Time.now.to_i}.png" filename = "#{Webrat.configuration.saved_pages_dir}/webrat-#{Time.now.to_i}.png"
if $browser.chrome_backend? if $browser.chrome_backend?
$browser.capture_entire_page_screenshot(filename, '') $browser.capture_entire_page_screenshot(filename, '')
@ -213,7 +237,7 @@ module Webrat
def create_browser def create_browser
$browser = ::Selenium::Client::Driver.new(Webrat.configuration.selenium_server_address || "localhost", $browser = ::Selenium::Client::Driver.new(Webrat.configuration.selenium_server_address || "localhost",
Webrat.configuration.selenium_server_port, Webrat.configuration.selenium_browser_key, "http://#{Webrat.configuration.application_address}:#{Webrat.configuration.application_port}") Webrat.configuration.selenium_server_port, Webrat.configuration.selenium_browser_key, "http://#{Webrat.configuration.application_address}:#{Webrat.configuration.application_port_for_selenium}")
$browser.set_speed(0) unless Webrat.configuration.selenium_server_address $browser.set_speed(0) unless Webrat.configuration.selenium_server_address
at_exit do at_exit do

View File

@ -15,4 +15,4 @@ module Webrat
end end
end end
end end
end end

View File

@ -10,16 +10,12 @@ module Webrat #:nodoc:
def initialize(*args) def initialize(*args)
end end
def doc_root
File.expand_path(File.join(".", "public"))
end
def response def response
@response ||= Object.new @response ||= Object.new
end end
def response_code def response_code
@response_code || 200 @response_code ||= 200
end end
def get(url, data, headers = nil) def get(url, data, headers = nil)

View File

@ -1,4 +1,3 @@
require "rubygems"
require "sinatra/base" require "sinatra/base"
class SampleApp < Sinatra::Default class SampleApp < Sinatra::Default
@ -17,4 +16,20 @@ class SampleApp < Sinatra::Default
get "/redirected" do get "/redirected" do
"Redirected" "Redirected"
end end
get "/form" do
<<-EOS
<html>
<form action="/form" method="post">
<input type="hidden" name="_method" value="put" />
<label for="email">Email:</label> <input type="text" id="email" name="email" /></label>
<input type="submit" value="Add" />
</form>
</html>
EOS
end
put "/form" do
"Welcome #{params[:email]}"
end
end end

View File

@ -12,7 +12,15 @@ describe "Webrat's Mechanize mode" do
end end
it "should follow links" it "should follow links"
it "should submit forms"
it "should submit forms" do
visit "http://localhost:9292/form"
fill_in "Email", :with => "albert@example.com"
response = click_button "Add"
response.should contain("Welcome albert@example.com")
end
it "should not follow external redirects" do it "should not follow external redirects" do
pending do pending do
response = visit("http://localhost:9292/external_redirect") response = visit("http://localhost:9292/external_redirect")

View File

@ -21,7 +21,9 @@ Spec::Runner.configure do |config|
end end
config.after :suite do config.after :suite do
Process.kill("TERM", File.read("rack.pid").to_i) if File.exists?("rack.pid")
Process.kill("TERM", File.read("rack.pid").to_i)
end
end end
end end

View File

@ -1,4 +1,3 @@
require "rubygems"
require "sinatra/base" require "sinatra/base"
class RackApp < Sinatra::Base class RackApp < Sinatra::Base
@ -39,7 +38,8 @@ class RackApp < Sinatra::Base
end end
post "/upload" do post "/upload" do
params[:uploaded_file].to_yaml uploaded_file = params[:uploaded_file]
Marshal.dump(:tempfile => uploaded_file[:tempfile].read, :type => uploaded_file[:type], :filename => uploaded_file[:filename])
end end
end end

View File

@ -1,4 +1,3 @@
require "rubygems"
require "test/unit" require "test/unit"
require "rack/test" require "rack/test"
# require "redgreen" # require "redgreen"

View File

@ -1,3 +1,4 @@
require "rubygems"
require File.dirname(__FILE__) + "/helper" require File.dirname(__FILE__) + "/helper"
class WebratRackTest < Test::Unit::TestCase class WebratRackTest < Test::Unit::TestCase
@ -52,10 +53,10 @@ class WebratRackTest < Test::Unit::TestCase
attach_file "File", __FILE__, "text/ruby" attach_file "File", __FILE__, "text/ruby"
click_button "Upload" click_button "Upload"
upload = YAML.load(response_body) upload = Marshal.load(response_body)
assert_equal "text/ruby", upload[:type] assert_equal "text/ruby", upload[:type]
assert_equal "webrat_rack_test.rb", upload[:filename] assert_equal "webrat_rack_test.rb", upload[:filename]
assert upload[:tempfile].respond_to?(:read) assert_equal File.read(__FILE__), upload[:tempfile]
end end
end end

View File

@ -40,4 +40,7 @@ class WebratController < ApplicationController
render :text => params.to_json render :text => params.to_json
end end
def within
end
end end

View File

@ -1,11 +1,9 @@
<h1 id='form_title' class='form title'>Webrat Buttons Form</h1> <h1 id='form_title' class='form title'>Webrat Buttons Form</h1>
<% form_tag "/buttons" do %> <% form_tag "/buttons" do %>
<input type="button" id="input_button_id" value="input_button_value" />
<input type="submit" id="input_submit_id" value="input_submit_value" /> <input type="submit" id="input_submit_id" value="input_submit_value" />
<input type="image" id="input_image_id" value="input_image_value" alt="input_image_alt" src="" /> <input type="image" id="input_image_id" value="input_image_value" alt="input_image_alt" src="" />
<button type="button" id="button_button_id" value="button_button_value">button_button_text</button>
<button type="submit" id="button_submit_id" value="button_submit_value">button_submit_text</button> <button type="submit" id="button_submit_id" value="button_submit_value">button_submit_text</button>
<button type="image" id="button_image_id" value="button_image_value">button_image_text</button> <button type="image" id="button_image_id" value="button_image_value">button_image_text</button>
<% end %> <% end %>

View File

@ -1,11 +1,9 @@
<h1 id='form_title' class='form title'>Webrat Buttons Form</h1> <h1 id='form_title' class='form title'>Webrat Buttons Form</h1>
<% form_tag submit_path do %> <% form_tag submit_path do %>
<input type="button" id="input_button_id" value="input_button_value">
<input type="submit" id="input_submit_id" value="input_submit_value"> <input type="submit" id="input_submit_id" value="input_submit_value">
<input type="image" id="input_image_id" value="input_image_value" alt="input_image_alt" src=""> <input type="image" id="input_image_id" value="input_image_value" alt="input_image_alt" src="">
<button type="button" id="button_button_id" value="button_button_value">button_button_text</button>
<button type="submit" id="button_submit_id" value="button_submit_value">button_submit_text</button> <button type="submit" id="button_submit_id" value="button_submit_value">button_submit_text</button>
<button type="image" id="button_image_id" value="button_image_value">button_image_text</button> <button type="image" id="button_image_id" value="button_image_value">button_image_text</button>
<% end %> <% end %>

View File

@ -0,0 +1,3 @@
<div id="new_object">
<a href="/">Edit Object</a>
</div>

View File

@ -1,4 +1,4 @@
RAILS_GEM_VERSION = '2.2.2' unless defined? RAILS_GEM_VERSION # RAILS_GEM_VERSION = '2.3.4' unless defined? RAILS_GEM_VERSION
require File.join(File.dirname(__FILE__), 'boot') require File.join(File.dirname(__FILE__), 'boot')

View File

@ -12,6 +12,7 @@ ActionController::Routing::Routes.draw do |map|
webrat.before_redirect_form "/before_redirect_form", :action => "before_redirect_form" webrat.before_redirect_form "/before_redirect_form", :action => "before_redirect_form"
webrat.redirect_to_show_params "/redirect_to_show_params", :action => "redirect_to_show_params" webrat.redirect_to_show_params "/redirect_to_show_params", :action => "redirect_to_show_params"
webrat.show_params "/show_params", :action => "show_params" webrat.show_params "/show_params", :action => "show_params"
webrat.within "/within", :action => "within"
webrat.root :action => "form" webrat.root :action => "form"
end end

View File

@ -1,80 +1,66 @@
require 'test_helper' require 'test_helper'
class ButtonClickTest < ActionController::IntegrationTest class ButtonClickTest < ActionController::IntegrationTest
# <button type="button" ...>
test "should click button with type button by id" do
visit buttons_path
click_button "button_button_id"
end
test "should click button with type button by value" do
visit buttons_path
click_button "button_button_value"
end
test "should click button with type button by html" do
visit buttons_path
click_button "button_button_text"
end
# <button type="submit" ...> # <button type="submit" ...>
test "should click button with type submit by id" do test "should click button with type submit by id" do
visit buttons_path visit buttons_path
click_button "button_submit_id" click_button "button_submit_id"
assert_contain "success"
end end
test "should click button with type submit by value" do test "should click button with type submit by value" do
visit buttons_path visit buttons_path
click_button "button_submit_value" click_button "button_submit_value"
assert_contain "success"
end end
test "should click button with type submit by html" do test "should click button with type submit by html" do
visit buttons_path visit buttons_path
click_button "button_submit_text" click_button "button_submit_text"
assert_contain "success"
end end
# <button type="image" ...> # <button type="image" ...>
test "should click button with type image by id" do test "should click button with type image by id" do
visit buttons_path visit buttons_path
click_button "button_image_id" click_button "button_image_id"
assert_contain "success"
end end
test "should click button with type image by value" do test "should click button with type image by value" do
visit buttons_path visit buttons_path
click_button "button_image_value" click_button "button_image_value"
assert_contain "success"
end end
test "should click button with type image by html" do test "should click button with type image by html" do
visit buttons_path visit buttons_path
click_button "button_image_text" click_button "button_image_text"
end assert_contain "success"
# <input type="button" ...>
test "should click image with type button by id" do
visit buttons_path
click_button "input_button_id"
end
test "should click input with type button by value" do
visit buttons_path
click_button "input_button_value"
end end
# <input type="submit" ...> # <input type="submit" ...>
test "should click input with type submit by id" do test "should click input with type submit by id" do
visit buttons_path visit buttons_path
click_button "input_submit_id" click_button "input_submit_id"
assert_contain "success"
end end
test "should click input with type submit by value" do test "should click input with type submit by value" do
visit buttons_path visit buttons_path
click_button "input_submit_value" click_button "input_submit_value"
assert_contain "success"
end end
# <input type="image" ...> # <input type="image" ...>
test "should click input with type image by id" do test "should click input with type image by id" do
visit buttons_path visit buttons_path
click_button "input_image_id" click_button "input_image_id"
assert_contain "success"
end end
test "should click input with type image by value" do test "should click input with type image by value" do
visit buttons_path visit buttons_path
click_button "input_image_value" click_button "input_image_value"
assert_contain "success"
end end
test "should click input with type image by alt" do test "should click input with type image by alt" do
visit buttons_path visit buttons_path
click_button "input_image_alt" click_button "input_image_alt"
assert_contain "success"
end end
end
end

View File

@ -21,4 +21,4 @@ class FillInTest < ActionController::IntegrationTest
visit fields_path visit fields_path
fill_in "[Field]:", :with => "value" fill_in "[Field]:", :with => "value"
end end
end end

View File

@ -24,4 +24,4 @@ class LinkClickTest < ActionController::IntegrationTest
click_link "Link With (parens)" click_link "Link With (parens)"
assert_contain("Link:link_with_parens") assert_contain("Link:link_with_parens")
end end
end end

View File

@ -22,11 +22,14 @@ class WebratTest < ActionController::IntegrationTest
check "TOS" check "TOS"
select "January" select "January"
click_button "Test" click_button "Test"
assert_contain "OK"
end end
test "should check the value of a field" do test "should check the value of a field" do
visit "/" webrat.simulate do
assert field_labeled("Prefilled").value, "text" visit "/"
assert field_labeled("Prefilled").value, "text"
end
end end
test "should not carry params through redirects" do test "should not carry params through redirects" do
@ -43,20 +46,26 @@ class WebratTest < ActionController::IntegrationTest
test "should follow internal redirects" do test "should follow internal redirects" do
visit internal_redirect_path visit internal_redirect_path
assert !response.redirect? webrat.simulate do
assert !response.redirect?
end
assert response.body.include?("OK") assert response.body.include?("OK")
end end
test "should not follow external redirects" do test "should not follow external redirects" do
visit external_redirect_path webrat.simulate do
assert response.redirect? visit external_redirect_path
assert response.redirect?
end
end end
test "should recognize the host header to follow redirects properly" do test "should recognize the host header to follow redirects properly" do
header "Host", "foo.bar" webrat.simulate do
visit host_redirect_path header "Host", "foo.bar"
assert !response.redirect? visit host_redirect_path
assert response.body.include?("OK") assert !response.redirect?
assert response.body.include?("OK")
end
end end
test "should click link by text" do test "should click link by text" do
@ -81,6 +90,23 @@ class WebratTest < ActionController::IntegrationTest
assert_have_selector "h1" assert_have_selector "h1"
end end
test "should accept an Object argument to #within and translate using dom_id" do
webrat.simulate do
visit within_path
object = Object.new
def object.id
nil
end
within(object) do
click_link "Edit Object"
end
assert_contain "Webrat Form"
end
end
# Firefox detects and prevents infinite redirects under Selenium # Firefox detects and prevents infinite redirects under Selenium
unless ENV['WEBRAT_INTEGRATION_MODE'] == 'selenium' unless ENV['WEBRAT_INTEGRATION_MODE'] == 'selenium'
test "should detect infinite redirects" do test "should detect infinite redirects" do

View File

@ -12,6 +12,7 @@ require "webrat"
Webrat.configure do |config| Webrat.configure do |config|
config.mode = ENV['WEBRAT_INTEGRATION_MODE'].to_sym config.mode = ENV['WEBRAT_INTEGRATION_MODE'].to_sym
config.selenium_browser_key = '*safari'
end end
ActionController::Base.class_eval do ActionController::Base.class_eval do

View File

@ -1,4 +1,3 @@
require "rubygems"
require "sinatra" require "sinatra"
use_in_file_templates! use_in_file_templates!

View File

@ -1,4 +1,3 @@
require "rubygems"
require "sinatra/base" require "sinatra/base"
class MyModularApp < Sinatra::Default class MyModularApp < Sinatra::Default

View File

@ -1,3 +1,4 @@
require "rubygems"
require File.dirname(__FILE__) + "/test_helper" require File.dirname(__FILE__) + "/test_helper"
require File.dirname(__FILE__) + "/../classic_app" require File.dirname(__FILE__) + "/../classic_app"

View File

@ -1,4 +1,3 @@
require "rubygems"
require "test/unit" require "test/unit"
# require "redgreen" # require "redgreen"

View File

@ -1,28 +1,17 @@
require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper") require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
describe Webrat::Configuration do describe Webrat::Configuration do
Spec::Matchers.define :parse_with_nokogiri do
match do |config|
config.parse_with_nokogiri?
end
end
Spec::Matchers.define :open_error_files do Spec::Matchers.define :open_error_files do
match do |config| match do |config|
config.open_error_files? config.open_error_files?
end end
end end
it "should have a mode" do it "should have a mode" do
Webrat.configuration.should respond_to(:mode) Webrat.configuration.should respond_to(:mode)
end end
it "should use Nokogiri as the parser by default" do
config = Webrat::Configuration.new
config.should parse_with_nokogiri
end
it "should open error files by default" do it "should open error files by default" do
config = Webrat::Configuration.new config = Webrat::Configuration.new
config.should open_error_files config.should open_error_files
@ -56,24 +45,6 @@ describe Webrat::Configuration do
config.selenium_server_port.should == 1234 config.selenium_server_port.should == 1234
end end
[:rails,
:selenium,
:rack,
:sinatra,
:mechanize].each do |mode|
it "should require correct lib when in #{mode} mode" do
config = Webrat::Configuration.new
config.should_receive(:require).with("webrat/#{mode}")
config.mode = mode
end
end
it "should require merb_adapter when in merb mode" do
config = Webrat::Configuration.new
config.should_receive(:require).with("webrat/merb_adapter")
config.mode = :merb
end
describe "Selenium" do describe "Selenium" do
before :each do before :each do
@config = Webrat::Configuration.new @config = Webrat::Configuration.new

View File

@ -2,18 +2,16 @@ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
module Webrat module Webrat
describe Field do describe Field do
unless RUBY_PLATFORM =~ /java/ it "should have nice inspect output" do
it "should have nice inspect output" do html = <<-HTML
html = <<-HTML <html>
<html> <input type='checkbox' checked='checked' />
<input type='checkbox' checked='checked' /> </html>
</html> HTML
HTML
element = Webrat::XML.css_search(Webrat::XML.document(html), "input").first element = Webrat::XML.document(html).css("input").first
checkbox = CheckboxField.new(nil, element) checkbox = CheckboxField.new(nil, element)
checkbox.inspect.should =~ /#<Webrat::CheckboxField @element=<input type=['"]checkbox['"] checked(=['"]checked['"])?\/?>>/ checkbox.inspect.should =~ /^#<Webrat::CheckboxField @element=/
end
end end
end end
@ -25,7 +23,7 @@ module Webrat
</html> </html>
HTML HTML
element = Webrat::XML.css_search(Webrat::XML.document(html), "input").first element = Webrat::XML.document(html).css("input").first
checkbox = CheckboxField.new(nil, element) checkbox = CheckboxField.new(nil, element)
checkbox.should be_checked checkbox.should be_checked
end end
@ -37,7 +35,7 @@ module Webrat
</html> </html>
HTML HTML
element = Webrat::XML.css_search(Webrat::XML.document(html), "input").first element = Webrat::XML.document(html).css("input").first
checkbox = CheckboxField.new(nil, element) checkbox = CheckboxField.new(nil, element)
checkbox.should_not be_checked checkbox.should_not be_checked
end end
@ -51,7 +49,7 @@ module Webrat
</html> </html>
HTML HTML
element = Webrat::XML.css_search(Webrat::XML.document(html), "input").first element = Webrat::XML.document(html).css("input").first
radio_button = RadioField.new(nil, element) radio_button = RadioField.new(nil, element)
radio_button.should be_checked radio_button.should be_checked
end end
@ -61,7 +59,7 @@ module Webrat
<html><input type='radio' /></html> <html><input type='radio' /></html>
HTML HTML
element = Webrat::XML.css_search(Webrat::XML.document(html), "input").first element = Webrat::XML.document(html).css("input").first
radio_button = RadioField.new(nil, element) radio_button = RadioField.new(nil, element)
radio_button.should_not be_checked radio_button.should_not be_checked
end end
@ -77,9 +75,9 @@ module Webrat
</html> </html>
HTML HTML
element = Webrat::XML.css_search(Webrat::XML.document(html), 'input').first element = Webrat::XML.document(html).css('input').first
text_field = TextField.new(nil, element) text_field = TextField.new(nil, element)
text_field.to_param.should == { 'email' => 'user@example.com' } text_field.to_query_string.should == 'email=user@example.com'
end end
end end
end end

View File

@ -0,0 +1,69 @@
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
describe "Multiple nested params" do
it "should be corretly posted" do
Webrat.configuration.mode = :rails
with_html <<-HTML
<html>
<form method="post" action="/family">
<div class="couple">
<div class="parent">
<select name="user[family][parents][0][][gender]">
<option selected="selected" value="Mother">Mother</option>
<option value="Father">Father</option>
</select>
<input type="text" value="Alice" name="user[family][parents][0][][name]" />
</div>
<div class="parent">
<select name="user[family][parents][0][][gender]">
<option value="Mother">Mother</option>
<option selected="selected" value="Father">Father</option>
</select>
<input type="text" value="Michael" name="user[family][parents][0][][name]" />
</div>
</div>
<div class="couple">
<div class="parent">
<select name="user[family][parents][1][][gender]">
<option selected="selected" value="Mother">Mother</option>
<option value="Father">Father</option>
</select>
<input type="text" value="Jenny" name="user[family][parents][1][][name]" />
</div>
</div>
<input type="submit" />
</form>
</html>
HTML
params = { "user" => { "family" => { "parents" => {
"0" => [ {"name" => "Alice", "gender"=>"Mother"}, {"name" => "Michael", "gender"=>"Father"} ],
"1" => [ {"name" => "Jenny", "gender"=>"Mother"} ]
}
}
}
}
webrat_session.should_receive(:post).with("/family", params)
click_button
end
it "should correctly construct a query string" do
Webrat.configuration.mode = :mechanize
with_html <<-HTML
<html>
<form method="get" action="/search">
<input type="text" name="query" value="my-query" />
<input type="submit" />
</form>
</html>
HTML
params = { "query" => "my-query" }
webrat_session.should_receive(:get).with("/search", params)
click_button
end
end

View File

@ -1,10 +0,0 @@
require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
describe Webrat::Logging do
it "should not log if there is no logger" do
klass = Class.new
klass.send(:include, Webrat::Logging)
klass.new.debug_log "Testing"
end
end

View File

@ -2,11 +2,6 @@ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
describe Webrat::Session do describe Webrat::Session do
it "should not have a doc_root" do
session = Webrat::Session.new
session.doc_root.should be_nil
end
it "should expose the current_dom" do it "should expose the current_dom" do
session = Webrat::Session.new session = Webrat::Session.new
@ -111,24 +106,6 @@ describe Webrat::Session do
webrat_session = Webrat::Session.new webrat_session = Webrat::Session.new
end end
it "should return true if the last response was a redirect and Fixnum#/ returns a Rational" do
# This happens if the ruby-units gem has been required
Fixnum.class_eval do
alias_method :original_divide, "/".to_sym
def /(other)
Rational(self, other)
end
end
webrat_session.stub!(:response_code => 301)
webrat_session.redirect?.should be_true
Fixnum.class_eval do
alias_method "/".to_sym, :original_divide
end
end
it "should return true if the last response was a redirect" do it "should return true if the last response was a redirect" do
webrat_session.stub!(:response_code => 301) webrat_session.stub!(:response_code => 301)
webrat_session.redirect?.should be_true webrat_session.redirect?.should be_true
@ -138,6 +115,11 @@ describe Webrat::Session do
webrat_session.stub!(:response_code => 200) webrat_session.stub!(:response_code => 200)
webrat_session.redirect?.should be_false webrat_session.redirect?.should be_false
end end
it "should return false if the last response was a 304 Not Modified" do
webrat_session.stub!(:response_code => 304)
webrat_session.redirect?.should be_false
end
end end
describe "#internal_redirect?" do describe "#internal_redirect?" do

View File

@ -1,8 +1,9 @@
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
require "webrat/mechanize"
describe Webrat::MechanizeAdapter do describe Webrat::MechanizeAdapter do
Mechanize = WWW::Mechanize if defined?(WWW::Mechanize)
before :each do before :each do
Webrat.configuration.mode = :mechanize Webrat.configuration.mode = :mechanize
end end
@ -11,6 +12,13 @@ describe Webrat::MechanizeAdapter do
@mech = Webrat::MechanizeAdapter.new @mech = Webrat::MechanizeAdapter.new
end end
describe "mechanize" do
it "should disable the following of redirects on the mechanize instance" do
mech = @mech.mechanize
mech.redirect_ok.should be_false
end
end
describe "post" do describe "post" do
def url def url
'http://test.host/users' 'http://test.host/users'
@ -26,7 +34,8 @@ describe Webrat::MechanizeAdapter do
it "should flatten model post data" do it "should flatten model post data" do
mechanize = mock(:mechanize) mechanize = mock(:mechanize)
WWW::Mechanize.stub!(:new => mechanize) mechanize.stub!(:redirect_ok=)
Mechanize.stub!(:new => mechanize)
mechanize.should_receive(:post).with(url, flattened_data) mechanize.should_receive(:post).with(url, flattened_data)
Webrat::MechanizeAdapter.new.post(url, data) Webrat::MechanizeAdapter.new.post(url, data)
end end
@ -72,4 +81,16 @@ describe Webrat::MechanizeAdapter do
@session.absolute_url(relative_url).should == 'https://test.host/wilma' @session.absolute_url(relative_url).should == 'https://test.host/wilma'
end end
end end
describe "response_headers" do
it "should return the Headers object from the response" do
mech = @mech.mechanize
resp = mock('Mechanize::File')
hdr = Mechanize::Headers.new
resp.should_receive(:header).and_return(hdr)
mech.stub!(:get).and_return(resp)
@mech.get('/', nil)
@mech.response_headers.should == hdr
end
end
end end

View File

@ -1,93 +0,0 @@
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
describe "attach_file with merb" do
before do
Webrat.configuration.mode = :merb
@filename = __FILE__
end
it "should fail if no file field found" do
with_html <<-HTML
<html>
<form method="post" action="/widgets">
</form>
</html>
HTML
lambda { attach_file("Doc", "/some/path") }.should raise_error(Webrat::NotFoundError)
end
it "should submit empty strings for blank file fields" do
with_html <<-HTML
<html>
<form method="post" action="/widgets">
<input type="file" id="widget_file" name="widget[file]" />
<input type="submit" />
</form>
</html>
HTML
webrat_session.should_receive(:post).with("/widgets", { "widget" => { "file" => "" } })
click_button
end
it "should submit the attached file" do
with_html <<-HTML
<html>
<form method="post" action="/widgets">
<label for="widget_file">Document</label>
<input type="file" id="widget_file" name="widget[file]" />
<input type="submit" />
</form>
</html>
HTML
webrat_session.should_receive(:post).with { |path, params|
path.should == "/widgets"
params.should have_key("widget")
params["widget"].should have_key("file")
params["widget"]["file"].should be_an_instance_of(File)
params["widget"]["file"].path.should == @filename
}
attach_file "Document", @filename
click_button
end
it "should support collections" do
with_html <<-HTML
<html>
<form method="post" action="/widgets">
<label for="widget_file1">Document</label>
<input type="file" id="widget_file1" name="widget[files][]" />
<label for="widget_file2">Spreadsheet</label>
<input type="file" id="widget_file2" name="widget[files][]" />
<input type="submit" />
</form>
</html>
HTML
webrat_session.should_receive(:post).with { |path, params|
path.should == "/widgets"
params.should have_key("widget")
params["widget"].should have_key("files")
params["widget"]["files"][0].should be_an_instance_of(File)
params["widget"]["files"][0].path.should == @filename
params["widget"]["files"][1].should be_an_instance_of(File)
params["widget"]["files"][1].path.should == @filename
}
attach_file "Document", @filename
attach_file "Spreadsheet", @filename
click_button
end
xit "should allow the content type to be specified" do
with_html <<-HTML
<html>
<form method="post" action="/widgets">
<label for="person_picture">Picture</label>
<input type="file" id="person_picture" name="person[picture]" />
<input type="submit" />
</form>
</html>
HTML
ActionController::TestUploadedFile.should_receive(:new).with(@filename, "image/png").any_number_of_times
attach_file "Picture", @filename, "image/png"
click_button
end
end

View File

@ -1,61 +0,0 @@
require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
require "webrat/merb"
describe Webrat::MerbAdapter do
it "should not pass empty params if data is and empty hash" do
session = Webrat::MerbAdapter.new
response = OpenStruct.new
response.status = 200
session.should_receive(:request).with('url', {:params=> nil, :method=>"GET", :headers=>nil}).and_return(response)
session.get('url', {}, nil)
end
%w{post put delete}.each do |request_method|
it "should call do request with method #{request_method.upcase} for a #{request_method} call" do
session = Webrat::MerbAdapter.new
response = OpenStruct.new
response.status = 200
session.should_receive(:request).with('url', {:params=>nil, :method=>request_method.upcase, :headers=>nil}).and_return(response)
session.send(request_method, 'url', {}, nil)
end
end
%w{post put}.each do |request_method|
it "should call do request with method #{request_method.upcase} with a file attachment" do
session = Webrat::MerbAdapter.new
response = OpenStruct.new
response.status = 200
file = File.new(__FILE__)
session.should_receive(:request).with { |path, env|
path.should == "url"
env[:method].should == request_method.upcase
env[:headers].should be_nil
env[:input].should be_an_instance_of(StringIO)
env["CONTENT_LENGTH"].should be_an_instance_of(Fixnum)
env["CONTENT_TYPE"].should match(/multipart.*boundary/)
}.and_return(response)
session.send(request_method, 'url', { :file => file }, nil)
end
end
context "a session with a response" do
before do
@session = Webrat::MerbAdapter.new
@response = OpenStruct.new
@response.status = 200
@response.body = 'test response'
@session.instance_variable_set(:@response, @response)
end
it "should return body of a request as a response_body" do
@session.response_body.should == @response.body
end
it "should return status of a request as a response_code" do
@session.response_code.should == @response.status
end
end
end

View File

@ -1,6 +1,6 @@
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper") require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
if defined?(Nokogiri::XML) && Webrat.configuration.parse_with_nokogiri? # if defined?(Nokogiri::XML) && Webrat.configuration.parse_with_nokogiri?
describe "Nokogiri Extension" do describe "Nokogiri Extension" do
include Webrat::Matchers include Webrat::Matchers
@ -74,4 +74,4 @@ if defined?(Nokogiri::XML) && Webrat.configuration.parse_with_nokogiri?
end end
end end
end end
end # end

View File

@ -78,4 +78,37 @@ describe "attach_file" do
attach_file "Picture", @filename, "image/png" attach_file "Picture", @filename, "image/png"
click_button click_button
end end
it "should support nested attributes" do
with_html <<-HTML
<html>
<form method="post" action="/albums">
<label for="photo_file1">Photo</label>
<input type="file" id="photo_file1" name="album[photos_attributes][][image]" />
<input type="submit" />
</form>
</html>
HTML
webrat_session.should_receive(:post).with("/albums", { "album" => { "photos_attributes" => [{"image" => @uploaded_file}] } })
attach_file "Photo", @filename
click_button
end
it "should support nested attributes with multiple files" do
with_html <<-HTML
<html>
<form method="post" action="/albums">
<label for="photo_file1">Photo 1</label>
<input type="file" id="photo_file1" name="album[photos_attributes][][image]" />
<label for="photo_file2">Photo 2</label>
<input type="file" id="photo_file2" name="album[photos_attributes][][image]" />
<input type="submit" />
</form>
</html>
HTML
webrat_session.should_receive(:post).with("/albums", { "album" => { "photos_attributes" => [{"image" => @uploaded_file}, {"image" => @uploaded_file}] } })
attach_file "Photo 1", @filename
attach_file "Photo 2", @filename
click_button
end
end end

View File

@ -1,7 +1,5 @@
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
require "webrat/rails"
describe Webrat::RailsAdapter do describe Webrat::RailsAdapter do
before :each do before :each do
Webrat.configuration.mode = :rails Webrat.configuration.mode = :rails
@ -78,35 +76,4 @@ describe Webrat::RailsAdapter do
end end
end end
it "should provide a saved_page_dir" do
Webrat::RailsAdapter.new(mock("integration session")).should respond_to(:saved_page_dir)
end
it "should provide a doc_root" do
Webrat::RailsAdapter.new(mock("integration session")).should respond_to(:doc_root)
end
it "should accept an ActiveRecord argument to #within and translate to a selector using dom_id" do
pending "Move this to spec/public/within_spec.rb"
body = <<-HTML
<a href="/page1">Edit</a>
<div id="new_object">
<a href="/page2">Edit</a>
</div>
HTML
response = mock("response", :body => body, :headers => {}, :code => 200)
@integration_session.stub!(:response => response)
@integration_session.should_receive(:get).with("/page2", {}, nil)
rails_session = Webrat::RailsAdapter.new(@integration_session)
object = Object.new
object.stub!(:id => nil)
rails_session.within(object) do
rails_session.click_link 'Edit'
end
end
end end

View File

@ -6,7 +6,7 @@ describe "Basic Auth HTTP headers" do
end end
it "should be present in visit" do it "should be present in visit" do
webrat_session.should_receive(:get).with("/", {}, {'HTTP_AUTHORIZATION' => "Basic dXNlcjpzZWNyZXQ=\n"}) webrat_session.should_receive(:get).with("/", {}, {'HTTP_AUTHORIZATION' => "Basic dXNlcjpzZWNyZXQ="})
visit("/") visit("/")
end end
@ -18,7 +18,18 @@ describe "Basic Auth HTTP headers" do
</form> </form>
</html> </html>
HTML HTML
webrat_session.should_receive(:post).with("/form1", {}, {'HTTP_AUTHORIZATION' => "Basic dXNlcjpzZWNyZXQ=\n"}) webrat_session.should_receive(:post).with("/form1", {}, {'HTTP_AUTHORIZATION' => "Basic dXNlcjpzZWNyZXQ="})
click_button click_button
end end
context "with long username and password combination" do
before do
basic_auth('user', 'secret1234567890123456789012345678901234567890123456789012345678901234567890')
end
it "should be present, without new lines, in visit" do
webrat_session.should_receive(:get).with("/", {}, {'HTTP_AUTHORIZATION' => "Basic dXNlcjpzZWNyZXQxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkw"})
visit("/")
end
end
end end

View File

@ -331,18 +331,16 @@ describe "click_button" do
end end
it "should properly handle HTML entities in textarea default values" do it "should properly handle HTML entities in textarea default values" do
pending "needs bug fix" do with_html <<-HTML
with_html <<-HTML <html>
<html> <form method="post" action="/posts">
<form method="post" action="/posts"> <textarea name="post[body]">Peanut butter &amp; jelly</textarea>
<textarea name="post[body]">Peanut butter &amp; jelly</textarea> <input type="submit" />
<input type="submit" /> </form>
</form> </html>
</html> HTML
HTML webrat_session.should_receive(:post).with("/posts", "post" => {"body" => "Peanut butter & jelly"})
webrat_session.should_receive(:post).with("/posts", "post" => {"body" => "Peanut butter & jelly"}) click_button
click_button
end
end end
it "should send default selected option value from select" do it "should send default selected option value from select" do

View File

@ -144,6 +144,27 @@ describe "click_link" do
click_link "Posts" click_link "Posts"
end end
it "should click rails 2.3.4 javascript links with authenticity tokens" do
with_html <<-HTML
<html>
<a href="/posts" onclick="var f = document.createElement('form');
f.style.display = 'none';
this.parentNode.appendChild(f);
f.method = 'POST';
f.action = this.href;
var s = document.createElement('input');
s.setAttribute('type', 'hidden');
s.setAttribute('name', 'authenticity_token');
s.setAttribute('value', 'aa79cb354597a60a3786e7e291ed4f74d77d3a62=/$a');
f.appendChild(s);
f.submit();
return false;">Posts</a>
</html>
HTML
webrat_session.should_receive(:post).with("/posts", "authenticity_token" => "aa79cb354597a60a3786e7e291ed4f74d77d3a62=/$a")
click_link "Posts"
end
it "should click rails javascript delete links" do it "should click rails javascript delete links" do
with_html <<-HTML with_html <<-HTML
<html> <html>

Some files were not shown because too many files have changed in this diff Show More