Compare commits

...

143 Commits
rack ... master

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
Bryan Helmkamp 759d7e4581 Regenerated gemspec for version 0.5.1 2009-08-18 00:42:57 -04:00
Bryan Helmkamp 35deb84a18 Version bump to 0.5.1 2009-08-18 00:42:31 -04:00
Bryan Helmkamp 887d2b07f3 Prep for 0.5.1 release 2009-08-18 00:42:24 -04:00
Bryan Helmkamp ad0c846f17 History 2009-08-18 00:39:53 -04:00
Damian Janowski 4a949e0e5a Fix logger issue when running inside Cucumber. 2009-08-14 13:05:20 -03:00
Bryan Helmkamp 66251b66ae Cleanup session initializaton in Webrat::Methods 2009-08-12 22:05:04 -04:00
Bryan Helmkamp ec43bb9546 Selenium is a session type, not an adapter type 2009-08-12 21:44:02 -04:00
Bryan Helmkamp 2e6bef3b57 Rename TestSession to TestAdapter 2009-08-12 21:42:01 -04:00
Bryan Helmkamp 17713c9036 MechanizeAdapter doesn't need to inherit from Session 2009-08-12 21:39:32 -04:00
Bryan Helmkamp 0412543e5a Add very basic spec for Mechanize 2009-08-12 21:37:15 -04:00
Bryan Helmkamp e4ea9134a7 Rename MechanizeSession to MechanizeAdapter 2009-08-12 20:54:29 -04:00
Bryan Helmkamp 89ec303db5 Rename RailsSession to RailsAdapter 2009-08-12 20:52:57 -04:00
Bryan Helmkamp 986682488e Rename MerbSession to MerbAdapter 2009-08-12 20:50:55 -04:00
Bryan Helmkamp 22a06000f9 Introduce session_class method 2009-08-12 20:44:32 -04:00
Bryan Helmkamp a8c5af2b7a Rename session_class method to adapter_class 2009-08-12 20:43:44 -04:00
Bryan Helmkamp b0b88a0d82 Rename SinatraSession to SinatraAdapter 2009-08-12 20:40:44 -04:00
Bryan Helmkamp 561525dd81 Rename RackSession to RackAdapter 2009-08-12 20:39:35 -04:00
Bryan Helmkamp 3670b19f66 Remove duplicate branch for :sinatra mode 2009-08-12 20:25:25 -04:00
Bryan Helmkamp d55802d26e History 2009-08-12 20:17:16 -04:00
Bryan Helmkamp 74d470ff10 Merge commit 'sr/rack-upload' 2009-08-12 20:16:57 -04:00
Bryan Helmkamp 25e46a00f6 History 2009-08-12 20:14:01 -04:00
Bryan Helmkamp 27a773e6b0 Merge commit 'sr/mime' into sr-mime
Conflicts:
	Rakefile
	lib/webrat.rb
2009-08-12 20:12:14 -04:00
Bryan Helmkamp 3cdf378dd7 Add description to gemspec 2009-08-12 12:22:06 -04:00
Bryan Helmkamp 6a85b6e444 Regenerated gemspec for version 0.5.0 2009-08-12 12:15:14 -04:00
Bryan Helmkamp b48f9d622f Version bump to 0.5.0 2009-08-12 12:14:32 -04:00
Bryan Helmkamp 083332cdd3 Prep for 0.5.0 release 2009-08-12 12:14:18 -04:00
Bryan Helmkamp 3952d46979 History 2009-08-12 11:50:17 -04:00
Simon Rozet 195f9c3544 Add Rack >= 1.0 as a dependency to gemspec 2009-06-26 01:43:12 +02:00
Simon Rozet 0a2b77c9c4 Require rack in lib/webrat.rb 2009-06-26 01:42:51 +02:00
Simon Rozet 6cda9c79b4 Implement Webrat::MIME on top of Rack::Mime 2009-06-26 01:39:22 +02:00
Simon Rozet 3760867d0f Implement file uploading for :rack 2009-06-25 23:41:51 +02:00
114 changed files with 1970 additions and 1525 deletions

5
.gitignore vendored
View File

@ -12,4 +12,7 @@ log
results
test_apps
*.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,4 +1,88 @@
== Git
== 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
* Minor enhancements
* Base Webrat::MIME on Rack::Mime (Simon Rozet)
* Support file uploads in Rack mode (Simon Rozet)
* Bug fixes
* Fix bug in Webrat::Methods preventing Selenium mode from working [#277]
== 0.5.0 / 2009-08-12
* Major enhancements
* Depreacate :rack_test and :sinatra in favor of :rack, which uses Rack::Test (Simon Rozet)
* Minor enhancements

100
Rakefile
View File

@ -1,50 +1,24 @@
begin
require 'jeweler'
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 = "TODO"
s.rubyforge_project = "webrat"
s.extra_rdoc_files = %w[README.rdoc MIT-LICENSE.txt History.txt]
# Dependencies
s.add_dependency "nokogiri", ">= 1.2.0"
# TODO: Add development dependencies
end
Jeweler::RubyforgeTasks.new
require 'spec/rake/spectask'
rescue LoadError
puts "Jeweler not available. Install it with: gem install jeweler"
end
# require 'spec'
require 'spec/rake/spectask'
require 'spec/rake/verify_rcov'
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
desc "Run specs"
task(:spec) { $stderr.puts '`gem install rspec` to run specs' }
else
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
end
RCov::VerifyTask.new(:verify_rcov => :rcov) do |t|
t.threshold = 96.2 # Make sure you have rcov 0.7 or higher!
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
desc "Run everything against multiruby"
@ -99,29 +73,29 @@ task :spec_deps do
end
end
task :prepare do
system "ln -s ../../../../.. ./spec/integration/rails/vendor/plugins/webrat"
end
namespace :spec do
desc "Run the integration specs"
task :integration => ["integration:rails", "integration:merb", "integration:sinatra", "integration:rack"]
task :integration => [
"integration:rack",
"integration:sinatra",
"integration:merb",
"integration:mechanize",
"integration:rails:webrat",
"integration:rails:selenium",
]
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
task :selenium 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
end
end
task :webrat 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
end
end
@ -130,7 +104,7 @@ namespace :spec do
desc "Run the Merb integration specs"
task :merb do
Dir.chdir "spec/integration/merb" do
result = system "rake spec"
result = system "rake -rubygems spec"
raise "Merb integration tests failed" unless result
end
end
@ -138,7 +112,7 @@ namespace :spec do
desc "Run the Sinatra integration specs"
task :sinatra do
Dir.chdir "spec/integration/sinatra" do
result = system "rake test"
result = system "rake -rubygems test"
raise "Sinatra integration tests failed" unless result
end
end
@ -146,10 +120,18 @@ namespace :spec do
desc "Run the Sinatra integration specs"
task :rack do
Dir.chdir "spec/integration/rack" do
result = system "rake test"
result = system "rake -rubygems test"
raise "Rack integration tests failed" unless result
end
end
desc "Run the Mechanize integration specs"
task :mechanize do
Dir.chdir "spec/integration/mechanize" do
result = system "rake -rubygems spec"
raise "Mechanize integration tests failed" unless result
end
end
end
end
@ -158,8 +140,4 @@ task :whitespace do
sh %{find . -name '*.rb' -exec sed -i '' 's/ *$//g' {} \\;}
end
if defined?(Jeweler)
task :spec => :check_dependencies
end
task :default => :spec
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.4.5

View File

@ -1,9 +1,18 @@
require "rack"
require "nokogiri"
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.
class WebratError < StandardError
end
end
require "nokogiri"
require "webrat/core/xml/nokogiri"
require "webrat/core"

View File

@ -1,11 +1,17 @@
require "mechanize"
module Webrat #:nodoc:
class MechanizeSession < Session #:nodoc:
class MechanizeAdapter #:nodoc:
extend Forwardable
Mechanize = WWW::Mechanize if defined?(WWW::Mechanize)
attr_accessor :response
alias :page :response
def initialize(*args)
end
def request_page(url, http_method, data) #:nodoc:
super(absolute_url(url), http_method, data)
end
@ -16,13 +22,19 @@ module Webrat #:nodoc:
def post(url, data, headers_argument_not_used = nil)
post_data = data.inject({}) do |memo, param|
case param.last
case param
when Hash
param.last.each {|attribute, value| memo["#{param.first}[#{attribute}]"] = value }
else
memo[param.first] = param.last
param.each {|attribute, value| memo[attribute] = value }
memo
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
memo
end
@response = mechanize.post(url, post_data)
end
@ -35,8 +47,16 @@ module Webrat #:nodoc:
@response.code.to_i
end
def response_headers
@response.header
end
def mechanize
@mechanize ||= WWW::Mechanize.new
@mechanize ||= begin
mechanize = Mechanize.new
mechanize.redirect_ok = false
mechanize
end
end
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

@ -1,7 +1,7 @@
require "rack/test"
module Webrat
class RackSession
class RackAdapter
extend Forwardable
def_delegators :@session, :get, :post, :put, :delete
@ -18,6 +18,10 @@ module Webrat
response.status
end
def response_headers
response.headers
end
def response
@session.last_response
end

View File

@ -1,11 +1,8 @@
require "webrat"
require "action_controller"
require "action_controller/integration"
require "webrat/integrations/rails"
require "action_controller/record_identifier"
module Webrat
class RailsSession #:nodoc:
class RailsAdapter #:nodoc:
include ActionController::RecordIdentifier
attr_reader :integration_session
@ -14,29 +11,6 @@ module Webrat
@integration_session = session
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)
do_request(:get, url, data, headers)
end
@ -61,6 +35,10 @@ module Webrat
response.code.to_i
end
def response_headers
response.headers
end
def xml_content_type?
response.headers["Content-Type"].to_s =~ /xml/
end
@ -97,10 +75,3 @@ module Webrat
end
end
end
module ActionController #:nodoc:
IntegrationTest.class_eval do
include Webrat::Methods
include Webrat::Matchers
end
end

View File

@ -1,7 +1,5 @@
require "webrat/rack"
module Webrat
class SinatraSession < RackSession
class SinatraAdapter < RackAdapter
def initialize(context)
app = context.respond_to?(:app) ? context.app : Sinatra::Application

View File

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

View File

@ -1,4 +1,5 @@
require "webrat/core_extensions/deprecate"
require "pathname"
module Webrat
@ -16,20 +17,20 @@ module Webrat
# Webrat can be configured using the Webrat.configure method. For example:
#
# Webrat.configure do |config|
# config.parse_with_nokogiri = false
# config.mode = :sinatra
# end
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.
attr_reader :mode # :nodoc:
# Save and open pages with error status codes (500-599) in a browser? Defualts to true.
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
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=
# 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
attr_accessor :application_framework
@ -57,13 +65,19 @@ module Webrat
# Set the timeout for waiting for the browser process to start
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
# loop? Defaults to 10
attr_accessor :infinite_redirect_limit
# Print out the full HTML on wait failure
# Defaults to false
attr_accessor :selenium_verbose_output
def initialize # :nodoc:
self.open_error_files = true
self.parse_with_nokogiri = true
self.application_environment = :test
self.application_port = 3001
self.application_address = 'localhost'
@ -72,12 +86,12 @@ module Webrat
self.infinite_redirect_limit = 10
self.selenium_browser_key = '*firefox'
self.selenium_browser_startup_timeout = 5
end
self.selenium_verbose_output = false
def parse_with_nokogiri? #:nodoc:
@parse_with_nokogiri ? true : false
tmp_dir = Pathname.new(Dir.pwd).join("tmp")
self.saved_pages_dir = tmp_dir.exist? ? tmp_dir : Dir.pwd
end
def open_error_files? #:nodoc:
@open_error_files ? true : false
end
@ -87,13 +101,11 @@ module Webrat
def mode=(mode)
@mode = mode.to_sym
# This is a temporary hack to support backwards compatibility
# with Merb 1.0.8 until it's updated to use the new Webrat.configure
# syntax
if @mode == :merb
require("webrat/merb_session")
else
require("webrat/#{mode}")
begin
require("webrat/integrations/#{mode}")
rescue LoadError
# Only some modes have integration code that needs to
# be loaded, so this is OK
end
end

View File

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

View File

@ -3,14 +3,14 @@ module Webrat
class Element # :nodoc:
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)
end
end
def self.load(session, element)
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
attr_reader :element
@ -21,7 +21,7 @@ module Webrat
end
def path
Webrat::XML.xpath_to(@element)
@element.path
end
def inspect

View File

@ -1,6 +1,7 @@
require "cgi"
require "digest/md5"
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"
@ -13,7 +14,7 @@ module Webrat
attr_reader :value
def self.xpath_search
[".//button", ".//input", ".//textarea", ".//select"]
".//button|.//input|.//textarea|.//select"
end
def self.xpath_search_excluding_hidden
@ -32,16 +33,21 @@ module Webrat
def self.load(session, element)
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
def self.field_class(element)
case element.name
when "button" then ButtonField
when "select" then SelectField
when "select"
if element.attributes["multiple"].nil?
SelectField
else
MultipleSelectField
end
when "textarea" then TextareaField
else
case Webrat::XML.attribute(element, "type")
case element["type"]
when "checkbox" then CheckboxField
when "hidden" then HiddenField
when "radio" then RadioField
@ -67,11 +73,11 @@ module Webrat
end
def id
Webrat::XML.attribute(@element, "id")
@element["id"]
end
def disabled?
@element.attributes.has_key?("disabled") && Webrat::XML.attribute(@element, "disabled") != 'false'
@element.attributes.has_key?("disabled") && @element["disabled"] != 'false'
end
def raise_error_if_disabled
@ -79,17 +85,17 @@ module Webrat
raise DisabledFieldError.new("Cannot interact with disabled form element (#{self})")
end
def to_param
def to_query_string
return nil if disabled?
case Webrat.configuration.mode
when :rails
parse_rails_request_params("#{name}=#{escaped_value}")
when :merb
::Merb::Parse.query("#{name}=#{escaped_value}")
else
{ name => value }
query_string = case Webrat.configuration.mode
when :rails, :merb, :rack, :sinatra
build_query_string
when :mechanize
build_query_string(false)
end
query_string
end
def set(value)
@ -102,18 +108,6 @@ module Webrat
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
Form.load(@session, form_element)
end
@ -128,11 +122,23 @@ module Webrat
end
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
def escaped_value
CGI.escape([*@value].first.to_s)
CGI.escape(@value.to_s)
end
def labels
@ -155,30 +161,14 @@ module Webrat
end
unless id.blank?
@label_elements += Webrat::XML.xpath_search(form.element, ".//label[@for = '#{id}']")
@label_elements += form.element.xpath(".//label[@for = '#{id}']")
end
@label_elements
end
def default_value
Webrat::XML.attribute(@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
@element["value"]
end
end
@ -188,7 +178,7 @@ module Webrat
[".//button", ".//input[@type = 'submit']", ".//input[@type = 'button']", ".//input[@type = 'image']"]
end
def to_param
def to_query_string
return nil if @value.nil?
super
end
@ -199,7 +189,7 @@ module Webrat
def click
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
end
@ -211,13 +201,13 @@ module Webrat
".//input[@type = 'hidden']"
end
def to_param
def to_query_string
if collection_name?
super
else
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
else
nil
@ -239,18 +229,18 @@ module Webrat
".//input[@type = 'checkbox']"
end
def to_param
def to_query_string
return nil if @value.nil?
super
end
def check
raise_error_if_disabled
set(Webrat::XML.attribute(@element, "value") || "on")
set(@element["value"] || "on")
end
def checked?
Webrat::XML.attribute(@element, "checked") == "checked"
@element["checked"] == "checked"
end
def uncheck
@ -261,8 +251,8 @@ module Webrat
protected
def default_value
if Webrat::XML.attribute(@element, "checked") == "checked"
Webrat::XML.attribute(@element, "value") || "on"
if @element["checked"] == "checked"
@element["value"] || "on"
else
nil
end
@ -284,7 +274,7 @@ module Webrat
".//input[@type = 'radio']"
end
def to_param
def to_query_string
return nil if @value.nil?
super
end
@ -295,11 +285,11 @@ module Webrat
option.set(nil)
end
set(Webrat::XML.attribute(@element, "value") || "on")
set(@element["value"] || "on")
end
def checked?
Webrat::XML.attribute(@element, "checked") == "checked"
@element["checked"] == "checked"
end
protected
@ -309,8 +299,8 @@ module Webrat
end
def default_value
if Webrat::XML.attribute(@element, "checked") == "checked"
Webrat::XML.attribute(@element, "value") || "on"
if @element["checked"] == "checked"
@element["value"] || "on"
else
nil
end
@ -327,7 +317,7 @@ module Webrat
protected
def default_value
Webrat::XML.inner_html(@element)
@element.inner_html
end
end
@ -341,31 +331,32 @@ module Webrat
attr_accessor :content_type
def set(value, content_type = nil)
@original_value = @value
@content_type ||= content_type
super(value)
@content_type = content_type
end
def to_param
if @value.nil?
super
else
replace_param_value(super, @value, test_uploaded_file)
end
def digest_value
@value ? Digest::MD5.hexdigest(self.object_id.to_s) : ""
end
protected
def to_query_string
@value.nil? ? set("") : set(digest_value)
super
end
def test_uploaded_file
return "" if @original_value.blank?
case Webrat.configuration.mode
when :rails
if content_type
ActionController::TestUploadedFile.new(@value, content_type)
ActionController::TestUploadedFile.new(@original_value, content_type)
else
ActionController::TestUploadedFile.new(@value)
ActionController::TestUploadedFile.new(@original_value)
end
when :merb
# TODO: support content_type
File.new(@value)
when :rack, :merb
Rack::Test::UploadedFile.new(@original_value, content_type)
end
end
@ -379,31 +370,69 @@ module Webrat
class ResetField < Field #:nodoc:
def self.xpath_search
".//input[@type = 'reset']"
[".//input[@type = 'reset']"]
end
end
class SelectField < Field #:nodoc:
def self.xpath_search
".//select"
[".//select[not(@multiple)]"]
end
def options
@options ||= SelectOption.load_all(@session, @element)
end
def unset(value)
@value = nil
end
protected
def default_value
selected_options = Webrat::XML.xpath_search(@element, ".//option[@selected = 'selected']")
selected_options = Webrat::XML.xpath_search(@element, ".//option[position() = 1]") if selected_options.empty?
selected_options = @element.xpath(".//option[@selected = 'selected']")
selected_options = @element.xpath(".//option[position() = 1]") if selected_options.empty?
selected_options.map do |option|
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
end
end

View File

@ -9,7 +9,7 @@ module Webrat
attr_reader :element
def self.xpath_search
".//form"
[".//form"]
end
def fields
@ -27,7 +27,7 @@ module Webrat
protected
def dom
Webrat::XML.xpath_at(@session.dom, path)
@session.dom.xpath(path).first
end
def fields_by_type(field_types)
@ -38,66 +38,90 @@ module Webrat
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
all_params = {}
query_string = []
replaces = {}
fields.each do |field|
next if field.to_param.nil?
merge(all_params, field.to_param)
next if field.to_query_string.nil?
replaces.merge!({field.digest_value => field.test_uploaded_file}) if field.is_a?(FileField)
query_string << field.to_query_string
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
def form_method
Webrat::XML.attribute(@element, "method").blank? ? :get : Webrat::XML.attribute(@element, "method").downcase
@element["method"].blank? ? :get : @element["method"].downcase
end
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
def merge(all_params, new_param)
new_param.each do |key, value|
case all_params[key]
when *hash_classes
merge_hash_values(all_params[key], value)
def self.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
all_params[key] += value
else
all_params[key] = value
value = value.map { |o| o == oval ? nval : ( o.is_a?(Hash) ? replace_param_value(o, oval, nval) : o) }
when oval
value = nval
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
def merge_hash_values(a, b) # :nodoc:
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]
def self.query_string_to_params(query_string)
case Webrat.configuration.mode
when :rails
klasses << HashWithIndifferentAccess
parse_rails_request_params(query_string)
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
klasses
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

View File

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

View File

@ -7,7 +7,7 @@ module Webrat
class Link < Element #:nodoc:
def self.xpath_search
".//a[@href]"
[".//a[@href]"]
end
def click(options = {})
@ -26,7 +26,7 @@ module Webrat
protected
def id
Webrat::XML.attribute(@element, "id")
@element["id"]
end
def data
@ -34,11 +34,11 @@ module Webrat
end
def title
Webrat::XML.attribute(@element, "title")
@element["title"]
end
def href
Webrat::XML.attribute(@element, "href")
@element["href"]
end
def absolute_href
@ -53,12 +53,12 @@ module Webrat
def 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
end
def onclick
Webrat::XML.attribute(@element, "onclick")
@element["onclick"]
end
def http_method

View File

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

View File

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

View File

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

View File

@ -20,24 +20,24 @@ module Webrat
end
def matches_id?(element)
(@value.is_a?(Regexp) && Webrat::XML.attribute(element, "id") =~ @value) ||
(!@value.is_a?(Regexp) && Webrat::XML.attribute(element, "id") == @value.to_s)
(@value.is_a?(Regexp) && element["id"] =~ @value) ||
(!@value.is_a?(Regexp) && element["id"] == @value.to_s)
end
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
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
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
def button_elements
Webrat::XML.xpath_search(@dom, *ButtonField.xpath_search)
@dom.xpath(*ButtonField.xpath_search)
end
def error_message

View File

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

View File

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

View File

@ -11,19 +11,19 @@ module Webrat
def 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
def field_elements
Webrat::XML.xpath_search(@dom, *xpath_searches)
@dom.xpath(*xpath_searches)
end
def xpath_searches
if @field_types.any?
@field_types.map { |field_type| field_type.xpath_search }.flatten
else
Array(Field.xpath_search)
Field.xpath_search
end
end

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,4 @@
require "webrat/core/xml/nokogiri"
require "webrat/core/xml/rexml"
require "webrat/core/xml"
module Webrat
module Matchers
@ -15,39 +14,17 @@ module Webrat
@block ||= block
matched = matches(stringlike)
@block.call(matched) if @block
if @options[:count]
matched.size == @options[:count] && (!@block || @block.call(matched))
matched.size == @options[:count].to_i
else
matched.any? && (!@block || @block.call(matched))
matched.any?
end
end
def matches(stringlike)
if Webrat.configuration.parse_with_nokogiri?
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
nokogiri_matches(stringlike)
end
def nokogiri_matches(stringlike)

View File

@ -3,7 +3,7 @@ module Webrat
def self.delegate_to_session(*meths)
meths.each do |meth|
self.class_eval <<-RUBY
self.class_eval(<<-RUBY, __FILE__, __LINE__)
def #{meth}(*args, &blk)
webrat_session.#{meth}(*args, &blk)
end
@ -16,11 +16,11 @@ module Webrat
end
def webrat_session
@_webrat_session ||= ::Webrat::Session.new(webrat_adapter)
end
def webrat_adapter
@_webrat_adapter ||= Webrat.session_class.new(self)
@_webrat_session ||= begin
session = Webrat.session_class.new
session.adapter = Webrat.adapter_class.new(self) if session.respond_to?(:adapter=)
session
end
end
# all of these methods delegate to the @session, which should
@ -39,6 +39,7 @@ module Webrat
:unchecks, :uncheck,
:chooses, :choose,
:selects, :select,
:unselects, :unselect,
:attaches_file, :attach_file,
:current_page,
:current_url,

View File

@ -1,29 +1,18 @@
module Webrat #:nodoc:
module MIME #:nodoc:
MIME_TYPES = Rack::Mime::MIME_TYPES.dup.merge(
".multipart_form" => "multipart/form-data",
".url_encoded_form" => "application/x-www-form-urlencoded"
).freeze
def self.mime_type(string_or_symbol) #:nodoc:
if string_or_symbol.is_a?(String)
string_or_symbol
else
case string_or_symbol
when :text then "text/plain"
when :html then "text/html"
when :js then "text/javascript"
when :css then "text/css"
when :ics then "text/calendar"
when :csv then "text/csv"
when :xml then "application/xml"
when :rss then "application/rss+xml"
when :atom then "application/atom+xml"
when :yaml then "application/x-yaml"
when :multipart_form then "multipart/form-data"
when :url_encoded_form then "application/x-www-form-urlencoded"
when :json then "application/json"
else
raise ArgumentError.new("Invalid Mime type: #{string_or_symbol.inspect}")
end
end
def mime_type(type)
return type if type.nil? || type.to_s.include?("/")
type = ".#{type}" unless type.to_s[0] == ?.
MIME_TYPES.fetch(type) { |invalid_type|
raise ArgumentError.new("Invalid Mime type: #{invalid_type}")
}
end
module_function :mime_type
end
end

View File

@ -6,12 +6,12 @@ module Webrat
# Example:
# 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|
f.write rewrite_css_and_image_references(response_body)
f.write response_body
end
open_in_browser(filename)
@ -24,25 +24,5 @@ module Webrat
warn "Sorry, you need to install launchy to open pages: `gem install launchy`"
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

View File

@ -28,6 +28,7 @@ module Webrat
attr_reader :session
def initialize(session, &block) #:nodoc:
@selector, @dom = nil
@session = session
instance_eval(&block) if block_given?
@ -112,6 +113,21 @@ module Webrat
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 = {
:year => '1i',
:month => '2i',
@ -312,12 +328,12 @@ module Webrat
dom = Webrat::XML.html_document(@response_body)
end
Webrat.define_dom_method(@response, dom)
Webrat::XML.define_dom_method(@response, dom)
return dom
end
def scoped_dom
Webrat::XML.css_at(@scope.dom, @selector)
@scope.dom.css(@selector).first
end
def locate_field(field_locator, *field_types) #:nodoc:

View File

@ -13,26 +13,30 @@ module Webrat
end
def self.session_class
if Webrat.configuration.mode == :selenium
SeleniumSession
else
Session
end
end
def self.adapter_class
case Webrat.configuration.mode
when :rails
RailsSession
RailsAdapter
when :merb
MerbSession
MerbAdapter
when :rack
RackSession
RackAdapter
when :rack_test
warn("The :rack_test mode is deprecated. Please use :rack instead")
require "webrat/rack"
RackSession
RackAdapter
when :sinatra
warn("The :sinatra mode is deprecated. Please use :rack instead")
SinatraSession
when :selenium
SeleniumSession
when :sinatra
SinatraSession
SinatraAdapter
when :mechanize
MechanizeSession
MechanizeAdapter
else
raise WebratError.new(<<-STR)
Unknown Webrat mode: #{Webrat.configuration.mode.inspect}
@ -55,20 +59,23 @@ For example:
extend Forwardable
include Logging
include SaveAndOpenPage
attr_accessor :adapter
attr_reader :current_url
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=,
:get, :post, :put, :delete
def initialize(adapter=nil)
def initialize(adapter = nil)
@adapter = adapter
@http_method = :get
@data = {}
@default_headers = {}
@custom_headers = {}
@adapter = adapter
@current_url = nil
reset
end
@ -86,10 +93,6 @@ For example:
page
end
def doc_root #:nodoc:
nil
end
def header(key, value)
@custom_headers[key] = value
end
@ -99,7 +102,7 @@ For example:
end
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}")
end
@ -153,7 +156,7 @@ For example:
end
def redirect? #:nodoc:
(response_code / 100).to_i == 3
[301, 302, 303, 307].include?(response_code)
end
def internal_redirect?
@ -254,6 +257,7 @@ For example:
def_delegators :current_scope, :uncheck, :unchecks
def_delegators :current_scope, :choose, :chooses
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_date, :selects_date
def_delegators :current_scope, :select_time, :selects_time
@ -278,7 +282,7 @@ For example:
end
def response_location
response.headers["Location"]
response_headers['Location']
end
def current_host

View File

@ -1,115 +1,72 @@
require "webrat/core/xml/nokogiri"
require "webrat/core/xml/hpricot"
require "webrat/core/xml/rexml"
require "webrat/core_extensions/meta_class"
module Webrat #:nodoc:
module XML #:nodoc:
def self.document(stringlike) #:nodoc:
if Webrat.configuration.parse_with_nokogiri?
Webrat.nokogiri_document(stringlike)
return stringlike.dom if stringlike.respond_to?(:dom)
if Nokogiri::HTML::Document === stringlike
stringlike
elsif Nokogiri::XML::NodeSet === stringlike
stringlike
elsif stringlike.respond_to?(:body)
Nokogiri::HTML(stringlike.body.to_s)
else
Webrat.rexml_document(Webrat.hpricot_document(stringlike).to_html)
Nokogiri::HTML(stringlike.to_s)
end
end
def self.html_document(stringlike) #:nodoc:
if Webrat.configuration.parse_with_nokogiri?
Webrat.html_nokogiri_document(stringlike)
return stringlike.dom if stringlike.respond_to?(:dom)
if Nokogiri::HTML::Document === stringlike
stringlike
elsif Nokogiri::XML::NodeSet === stringlike
stringlike
elsif stringlike.respond_to?(:body)
Nokogiri::HTML(stringlike.body.to_s)
else
Webrat.rexml_document(Webrat.hpricot_document(stringlike).to_html)
Nokogiri::HTML(stringlike.to_s)
end
end
def self.xml_document(stringlike) #:nodoc:
if Webrat.configuration.parse_with_nokogiri?
Webrat.xml_nokogiri_document(stringlike)
return stringlike.dom if stringlike.respond_to?(:dom)
if Nokogiri::HTML::Document === stringlike
stringlike
elsif Nokogiri::XML::NodeSet === stringlike
stringlike
elsif stringlike.respond_to?(:body)
Nokogiri::XML(stringlike.body.to_s)
else
Webrat.rexml_document(Webrat.hpricot_document(stringlike).to_html)
Nokogiri::XML(stringlike.to_s)
end
end
def self.to_html(element)
if Webrat.configuration.parse_with_nokogiri?
element.to_html
else
element.to_s
def self.define_dom_method(object, dom) #:nodoc:
object.meta_class.send(:define_method, :dom) do
dom
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
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:
def to_param
def to_query_string
nil
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,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,82 +0,0 @@
require "webrat"
require "merb-core"
require "webrat/merb_multipart_support"
module Webrat
class MerbSession #: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::MerbSession.new
@_webrat_session.response = @_webrat_session.request(uri, env)
end
end
end
end

View File

@ -1,10 +1,2 @@
# 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/rspec-rails'
#
require "webrat/core/matchers"
Spec::Runner.configure do |config|
config.include(Webrat::Matchers, :type => [:controller, :helper, :view])
end
warn("Requiring 'webrat/rspec-rails' is deprecated. Please require 'webrat/integrations/rspec-rails' instead")
require "webrat/integrations/rspec-rails"

View File

@ -68,13 +68,3 @@ module Webrat
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/merb"
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

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 regExp = new RegExp('^\\W*' + RegExp.escape(locator) + '(\\b|$)', 'i');
var candidateLabels = $A(allLabels).select(function(candidateLabel){
var regExp = new RegExp('^' + locator + '\\b', 'i');
var labelText = getText(candidateLabel).strip();
return (labelText.search(regExp) >= 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 labelFor = locatedLabel.getAttribute('for');
if ((labelFor == null) && (locatedLabel.hasChildNodes())) {
return locatedLabel.firstChild; //TODO: should find the first form field, not just any node
var labelFor = null;
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);

View File

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

View File

@ -1,12 +1,32 @@
var links = inDocument.getElementsByTagName('a');
var candidateLinks = $A(links).select(function(candidateLink) {
var textMatched = PatternMatcher.matches(locator, getText(candidateLink));
var idMatched = PatternMatcher.matches(locator, candidateLink.id);
var titleMatched = PatternMatcher.matches(locator, candidateLink.title);
var textMatched = false;
var titleMatched = false;
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;
});
if (candidateLinks.length == 0) {
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();

View File

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

View File

@ -14,6 +14,14 @@ module Webrat
false
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
# String:: The failure message.
def failure_message

View File

@ -14,6 +14,14 @@ module Webrat
false
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
# String:: The failure message.
def failure_message

View File

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

View File

@ -3,6 +3,13 @@ require "webrat/selenium/selenium_rc_server"
require "webrat/selenium/application_server_factory"
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
class TimeoutError < WebratError
end
@ -77,7 +84,12 @@ module Webrat
webrat_deprecate :clicks_button, :click_button
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}"
selenium.wait_for_element locator, :timeout_in_seconds => 5
selenium.click locator
@ -162,7 +174,19 @@ module Webrat
sleep 0.25
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
end
@ -176,9 +200,9 @@ module Webrat
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?
$browser.capture_entire_page_screenshot(filename, '')
@ -213,7 +237,7 @@ module Webrat
def create_browser
$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
at_exit do

View File

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

View File

@ -1,14 +1,13 @@
module Webrat #:nodoc:
def self.session_class #:nodoc:
TestSession
def self.adapter_class #:nodoc:
TestAdapter
end
class TestSession < Session #:nodoc:
class TestAdapter #:nodoc:
attr_accessor :response_body
attr_writer :response_code
def doc_root
File.expand_path(File.join(".", "public"))
def initialize(*args)
end
def response
@ -16,7 +15,7 @@ module Webrat #:nodoc:
end
def response_code
@response_code || 200
@response_code ||= 200
end
def get(url, data, headers = nil)

View File

@ -0,0 +1,7 @@
require 'rubygems'
require 'spec/rake/spectask'
Spec::Rake::SpecTask.new do |t|
t.spec_opts = ['--color']
t.spec_files = FileList['spec/**/*_spec.rb']
end

View File

@ -0,0 +1,2 @@
require "sample_app"
run SampleApp

View File

@ -0,0 +1,35 @@
require "sinatra/base"
class SampleApp < Sinatra::Default
get "/" do
"Hello World"
end
get "/internal_redirect" do
redirect URI.join(request.url, "redirected").to_s
end
get "/external_redirect" do
redirect "http://example.tst/"
end
get "/redirected" do
"Redirected"
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

View File

@ -0,0 +1,30 @@
require File.dirname(__FILE__) + "/spec_helper"
describe "Webrat's Mechanize mode" do
it "should work" do
response = visit("http://localhost:9292/")
response.should contain("Hello World")
end
it "should follow redirects" do
response = visit("http://localhost:9292/internal_redirect")
response.should contain("Redirected")
end
it "should follow links"
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
pending do
response = visit("http://localhost:9292/external_redirect")
response.should contain("Foo")
end
end
end

View File

@ -0,0 +1,29 @@
require "rubygems"
require "spec"
$LOAD_PATH.unshift File.dirname(__FILE__) + "/../../../../lib"
require "webrat"
Webrat.configure do |config|
config.mode = :mechanize
end
Spec::Runner.configure do |config|
config.include Webrat::Methods
config.include Webrat::Matchers
config.before :suite do
if File.exists?("rack.pid")
Process.kill("TERM", File.read("rack.pid").to_i)
end
system "rackup --daemonize --pid rack.pid config.ru"
end
config.after :suite do
if File.exists?("rack.pid")
Process.kill("TERM", File.read("rack.pid").to_i)
end
end
end

View File

@ -1,5 +1,7 @@
require "rubygems"
$LOAD_PATH.unshift File.dirname(__FILE__) + "/../../../../lib"
# Add the local gems dir if found within the app root; any dependencies loaded
# hereafter will try to load from the local gems before loading system gems.
if (local_gem_dir = File.join(File.dirname(__FILE__), '..', 'gems')) && $BUNDLE.nil?

View File

@ -1,4 +1,3 @@
require "rubygems"
require "sinatra/base"
class RackApp < Sinatra::Base
@ -33,6 +32,15 @@ class RackApp < Sinatra::Base
@email = params[:email]
erb :hello
end
get "/upload" do
erb :uploader
end
post "/upload" do
uploaded_file = params[:uploaded_file]
Marshal.dump(:tempfile => uploaded_file[:tempfile].read, :type => uploaded_file[:type], :filename => uploaded_file[:filename])
end
end
__END__
@ -71,3 +79,11 @@ __END__
@@ hello
<p>Hello, <%= @user %></p>
<p>Your email is: <%= @email %></p>
@@ uploader
<form action="/upload" method="post">
<label>
File <input type="file" name="uploaded_file" />
</label>
<input type="submit" value="Upload">
</form>

View File

@ -1,9 +1,9 @@
require "rubygems"
require "test/unit"
require "rack/test"
# require "redgreen"
require File.dirname(__FILE__) + "/../../../../lib/webrat"
$LOAD_PATH.unshift File.dirname(__FILE__) + "/../../../../lib"
require "webrat"
require File.dirname(__FILE__) + "/../app"
Webrat.configure do |config|

View File

@ -1,3 +1,4 @@
require "rubygems"
require File.dirname(__FILE__) + "/helper"
class WebratRackTest < Test::Unit::TestCase
@ -46,12 +47,23 @@ class WebratRackTest < Test::Unit::TestCase
visit "/absolute_redirect"
assert_contain "spam"
end
def test_upload_file
visit "/upload"
attach_file "File", __FILE__, "text/ruby"
click_button "Upload"
upload = Marshal.load(response_body)
assert_equal "text/ruby", upload[:type]
assert_equal "webrat_rack_test.rb", upload[:filename]
assert_equal File.read(__FILE__), upload[:tempfile]
end
end
class WebratRackSetupTest < Test::Unit::TestCase
def test_usable_without_mixin
rack_test_session = Rack::Test::Session.new(Rack::MockSession.new(app))
adapter = Webrat::RackSession.new(rack_test_session)
adapter = Webrat::RackAdapter.new(rack_test_session)
session = Webrat::Session.new(adapter)
session.visit "/foo"

View File

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

View File

@ -1,11 +1,9 @@
<h1 id='form_title' class='form title'>Webrat Buttons Form</h1>
<% 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="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="image" id="button_image_id" value="button_image_value">button_image_text</button>
<% end %>

View File

@ -1,11 +1,9 @@
<h1 id='form_title' class='form title'>Webrat Buttons Form</h1>
<% 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="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="image" id="button_image_id" value="button_image_value">button_image_text</button>
<% 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')

View File

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

View File

@ -1,80 +1,66 @@
require 'test_helper'
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" ...>
test "should click button with type submit by id" do
visit buttons_path
click_button "button_submit_id"
assert_contain "success"
end
test "should click button with type submit by value" do
visit buttons_path
click_button "button_submit_value"
assert_contain "success"
end
test "should click button with type submit by html" do
visit buttons_path
click_button "button_submit_text"
assert_contain "success"
end
# <button type="image" ...>
test "should click button with type image by id" do
visit buttons_path
click_button "button_image_id"
assert_contain "success"
end
test "should click button with type image by value" do
visit buttons_path
click_button "button_image_value"
assert_contain "success"
end
test "should click button with type image by html" do
visit buttons_path
click_button "button_image_text"
end
# <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"
assert_contain "success"
end
# <input type="submit" ...>
test "should click input with type submit by id" do
visit buttons_path
click_button "input_submit_id"
assert_contain "success"
end
test "should click input with type submit by value" do
visit buttons_path
click_button "input_submit_value"
assert_contain "success"
end
# <input type="image" ...>
test "should click input with type image by id" do
visit buttons_path
click_button "input_image_id"
assert_contain "success"
end
test "should click input with type image by value" do
visit buttons_path
click_button "input_image_value"
assert_contain "success"
end
test "should click input with type image by alt" do
visit buttons_path
click_button "input_image_alt"
assert_contain "success"
end
end
end

View File

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

View File

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

View File

@ -22,11 +22,14 @@ class WebratTest < ActionController::IntegrationTest
check "TOS"
select "January"
click_button "Test"
assert_contain "OK"
end
test "should check the value of a field" do
visit "/"
assert field_labeled("Prefilled").value, "text"
webrat.simulate do
visit "/"
assert field_labeled("Prefilled").value, "text"
end
end
test "should not carry params through redirects" do
@ -43,20 +46,26 @@ class WebratTest < ActionController::IntegrationTest
test "should follow internal redirects" do
visit internal_redirect_path
assert !response.redirect?
webrat.simulate do
assert !response.redirect?
end
assert response.body.include?("OK")
end
test "should not follow external redirects" do
visit external_redirect_path
assert response.redirect?
webrat.simulate do
visit external_redirect_path
assert response.redirect?
end
end
test "should recognize the host header to follow redirects properly" do
header "Host", "foo.bar"
visit host_redirect_path
assert !response.redirect?
assert response.body.include?("OK")
webrat.simulate do
header "Host", "foo.bar"
visit host_redirect_path
assert !response.redirect?
assert response.body.include?("OK")
end
end
test "should click link by text" do
@ -81,6 +90,23 @@ class WebratTest < ActionController::IntegrationTest
assert_have_selector "h1"
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
unless ENV['WEBRAT_INTEGRATION_MODE'] == 'selenium'
test "should detect infinite redirects" do

View File

@ -7,10 +7,12 @@ require 'test_help'
# rescue MissingSourceFile
# end
require File.dirname(__FILE__) + "/../../../../lib/webrat"
$LOAD_PATH.unshift File.dirname(__FILE__) + "/../../../../lib"
require "webrat"
Webrat.configure do |config|
config.mode = ENV['WEBRAT_INTEGRATION_MODE'].to_sym
config.selenium_browser_key = '*safari'
end
ActionController::Base.class_eval do

View File

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

View File

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

View File

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

View File

@ -1,8 +1,8 @@
require "rubygems"
require "test/unit"
# require "redgreen"
require File.dirname(__FILE__) + "/../../../../lib/webrat"
$LOAD_PATH.unshift File.dirname(__FILE__) + "/../../../../lib"
require "webrat"
Webrat.configure do |config|
config.mode = :sinatra

View File

@ -1,28 +1,17 @@
require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
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
match do |config|
config.open_error_files?
end
end
it "should have a mode" do
Webrat.configuration.should respond_to(:mode)
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
config = Webrat::Configuration.new
config.should open_error_files
@ -56,24 +45,6 @@ describe Webrat::Configuration do
config.selenium_server_port.should == 1234
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_session when in merb mode" do
config = Webrat::Configuration.new
config.should_receive(:require).with("webrat/merb_session")
config.mode = :merb
end
describe "Selenium" do
before :each do
@config = Webrat::Configuration.new

View File

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

@ -4,7 +4,7 @@ describe Webrat::Link do
# include Webrat::Link
before do
webrat_session = mock(Webrat::TestSession)
webrat_session = mock(Webrat::TestAdapter)
@link_text_with_nbsp = 'Link' + [0xA0].pack("U") + 'Text'
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
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
session = Webrat::Session.new
@ -62,6 +57,11 @@ describe Webrat::Session do
it "should raise an error if a symbol Mime type is passed that does not exist" do
lambda { webrat_session.http_accept(:oogabooga) }.should raise_error(ArgumentError)
end
it "should recognize a couple of webrat-specific formats" do
webrat_session.http_accept(:multipart_form).should == "multipart/form-data"
webrat_session.http_accept(:url_encoded_form).should == "application/x-www-form-urlencoded"
end
end
describe "#request_page" do
@ -106,24 +106,6 @@ describe Webrat::Session do
webrat_session = Webrat::Session.new
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
webrat_session.stub!(:response_code => 301)
webrat_session.redirect?.should be_true
@ -133,6 +115,11 @@ describe Webrat::Session do
webrat_session.stub!(:response_code => 200)
webrat_session.redirect?.should be_false
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
describe "#internal_redirect?" do

View File

@ -1,19 +1,21 @@
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
require "webrat/mechanize"
describe Webrat::MechanizeAdapter do
Mechanize = WWW::Mechanize if defined?(WWW::Mechanize)
describe Webrat::MechanizeSession do
before :each do
Webrat.configuration.mode = :mechanize
end
before(:each) do
@mech = Webrat::MechanizeSession.new
@mech = Webrat::MechanizeAdapter.new
end
describe "headers method" do
it "should return empty headers for a newly initialized session" do
@mech.headers.should == {}
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
@ -32,15 +34,16 @@ describe Webrat::MechanizeSession do
it "should flatten model post data" do
mechanize = mock(:mechanize)
WWW::Mechanize.stub!(:new => mechanize)
mechanize.stub!(:redirect_ok=)
Mechanize.stub!(:new => mechanize)
mechanize.should_receive(:post).with(url, flattened_data)
Webrat::MechanizeSession.new.post(url, data)
Webrat::MechanizeAdapter.new.post(url, data)
end
end
describe "#absolute_url" do
before(:each) do
@session = Webrat::MechanizeSession.new
@session = Webrat::MechanizeAdapter.new
@session.stub!(:current_url).and_return(absolute_url)
end
@ -78,4 +81,16 @@ describe Webrat::MechanizeSession do
@session.absolute_url(relative_url).should == 'https://test.host/wilma'
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

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::MerbSession do
it "should not pass empty params if data is and empty hash" do
session = Webrat::MerbSession.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::MerbSession.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::MerbSession.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::MerbSession.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")
if defined?(Nokogiri::XML) && Webrat.configuration.parse_with_nokogiri?
# if defined?(Nokogiri::XML) && Webrat.configuration.parse_with_nokogiri?
describe "Nokogiri Extension" do
include Webrat::Matchers
@ -74,4 +74,4 @@ if defined?(Nokogiri::XML) && Webrat.configuration.parse_with_nokogiri?
end
end
end
end
# end

View File

@ -78,4 +78,37 @@ describe "attach_file" do
attach_file "Picture", @filename, "image/png"
click_button
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

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