Compare commits
402 Commits
0-4-stable
...
master
Author | SHA1 | Date |
---|---|---|
John Bintz | 5e4ffeae9f | |
John Bintz | 0856d8d405 | |
Bryan Helmkamp | 8f637e6785 | |
Bryan Helmkamp | 312c175384 | |
Damian Janowski | 7cde0573c0 | |
Luismi Cavalle | 43b19eeafa | |
Damian Janowski | 107bdf7cf9 | |
Damian Janowski | 71a281066e | |
Damian Janowski | 438e53c295 | |
Noah Davis | 80ea640901 | |
Noah Davis | 68d5fde17a | |
Damian Janowski | 1979a7fc7f | |
Álvaro Gil | 06bb72d24f | |
Damian Janowski | c49123c772 | |
Damian Janowski | 2c9de38129 | |
Damian Janowski | 2a6c67b17b | |
Damian Janowski | 38e699820f | |
Damian Janowski | 4c62279fc1 | |
Damian Janowski | deccefa2c3 | |
Simon Rozet | 10c70a37de | |
Damian Janowski | 19fc2ccb89 | |
Larry Marburger | fd944cccb5 | |
Damian Janowski | 0bbf163d4f | |
Damian Janowski | ef6874c855 | |
Damian Janowski | e3bcf5c599 | |
Damian Janowski | bd6cd436de | |
Álvaro Gil | e36487458f | |
Álvaro Gil | c49e23d81d | |
Álvaro Gil | 15102bd60d | |
Álvaro Gil | fa881a88c8 | |
Noah Davis | 2f12422ae8 | |
Emrys Ingersoll | 67febe9072 | |
Emrys Ingersoll | 56b2f342da | |
Emrys Ingersoll | b2dddf2f09 | |
lukemelia | d9d9cc1fcc | |
Noah Davis | 0387d9eacc | |
Noah Davis | d73eca71ee | |
Noah Davis | 8d2fa24b4a | |
Bryan Helmkamp | eb3a4ff5d6 | |
hpoydar | 4ac8456a48 | |
Noah Davis | 3159ae081f | |
Noah Davis | ccaf41160c | |
Noah Davis | d50d24e09e | |
Noah Davis | 1874f6d395 | |
Noah Davis | 71dcfb327d | |
Noah Davis | db168bedec | |
lukemelia | f9985cd488 | |
Bryan Helmkamp | b64d68a2a8 | |
Bryan Helmkamp | 4081fe5538 | |
Bryan Helmkamp | 3bd7266ab9 | |
Bryan Helmkamp | a9ff3efcd7 | |
Michael Klett | 61b0fce828 | |
Bryan Helmkamp | f9f2a98189 | |
David Chelimsky | 51bdded2ce | |
Bryan Helmkamp | 4de7d64776 | |
Bryan Helmkamp | 13d513837a | |
Bryan Helmkamp | ba95363486 | |
Bryan Helmkamp | 672bd583af | |
Bryan Helmkamp | 0536360773 | |
Jonathan Weiss | ea4a52ccf1 | |
Bryan Helmkamp | cbb07306d4 | |
Bryan Helmkamp | 5a05d860ec | |
Bryan Helmkamp | 05af4dd2a0 | |
Bryan Helmkamp | 7812f25741 | |
Bryan Helmkamp | fcde80f43f | |
Bryan Helmkamp | 1ce72b6912 | |
Bryan Helmkamp | bb282d992e | |
Bryan Helmkamp | f6dd24f7c5 | |
Bryan Helmkamp | d0cadf8a76 | |
Bryan Helmkamp | 1c28425583 | |
David Chelimsky | 9a92afedff | |
Bryan Helmkamp | f51b745e89 | |
Bryan Helmkamp | 8dacd973aa | |
Bryan Helmkamp | 194d3250cc | |
Bryan Helmkamp | b68c6859e8 | |
Bryan Helmkamp | 87c54dde2e | |
Bryan Helmkamp | 042b416092 | |
Bryan Helmkamp | 40d7f970e0 | |
Bryan Helmkamp | 03f2023117 | |
Bryan Helmkamp | b51ba029db | |
Bryan Helmkamp | 862471476f | |
Bryan Helmkamp | c689166c48 | |
Bryan Helmkamp | 3a9e7d3999 | |
Bryan Helmkamp | 63e1053afa | |
Bryan Helmkamp | aae82b5111 | |
Bryan Helmkamp | e7a3ac865c | |
Bryan Helmkamp | 8772505322 | |
Bryan Helmkamp | b0ef59f5ec | |
Bryan Helmkamp | ad06a777fb | |
Bryan Helmkamp | 756a0c62ba | |
Bryan Helmkamp | 63591a8c30 | |
Bryan Helmkamp | ecaed5ff93 | |
Bryan Helmkamp | b0a8922eb4 | |
Bryan Helmkamp | 2490c247d2 | |
Bryan Helmkamp | 00c49a0521 | |
Bryan Helmkamp | b7ea26841e | |
Kieran Pilkington | a8d0cebde3 | |
Bryan Helmkamp | 98efa54900 | |
Bryan Helmkamp | 49c25027e9 | |
Bryan Helmkamp | 6fd9732b4e | |
Bryan Helmkamp | b9466df773 | |
Michael Christenson II | 3255c9edf0 | |
Bryan Helmkamp | 5b90488f29 | |
Bryan Helmkamp | f1cd50d615 | |
Bryan Helmkamp | e18ef197b5 | |
Bryan Helmkamp | 755abb7e07 | |
Bryan Helmkamp | 723f4356b9 | |
Bryan Helmkamp | 2fc9f3f7f9 | |
Bryan Helmkamp | 610f0fc217 | |
Bryan Helmkamp | 11f30d1d2e | |
Simon Rozet | 997ff97405 | |
Bryan Helmkamp | ab745d786c | |
Bryan Helmkamp | 759d7e4581 | |
Bryan Helmkamp | 35deb84a18 | |
Bryan Helmkamp | 887d2b07f3 | |
Bryan Helmkamp | ad0c846f17 | |
Damian Janowski | 4a949e0e5a | |
Bryan Helmkamp | 66251b66ae | |
Bryan Helmkamp | ec43bb9546 | |
Bryan Helmkamp | 2e6bef3b57 | |
Bryan Helmkamp | 17713c9036 | |
Bryan Helmkamp | 0412543e5a | |
Bryan Helmkamp | e4ea9134a7 | |
Bryan Helmkamp | 89ec303db5 | |
Bryan Helmkamp | 986682488e | |
Bryan Helmkamp | 22a06000f9 | |
Bryan Helmkamp | a8c5af2b7a | |
Bryan Helmkamp | b0b88a0d82 | |
Bryan Helmkamp | 561525dd81 | |
Bryan Helmkamp | 3670b19f66 | |
Bryan Helmkamp | d55802d26e | |
Bryan Helmkamp | 74d470ff10 | |
Bryan Helmkamp | 25e46a00f6 | |
Bryan Helmkamp | 27a773e6b0 | |
Bryan Helmkamp | 3cdf378dd7 | |
Bryan Helmkamp | 6a85b6e444 | |
Bryan Helmkamp | b48f9d622f | |
Bryan Helmkamp | 083332cdd3 | |
Bryan Helmkamp | 3952d46979 | |
Bryan Helmkamp | 25c1d7c783 | |
Kamal Fariz Mahyuddin | d9ebabf461 | |
Bryan Helmkamp | 0c7fa65880 | |
Bryan Helmkamp | 19ca271bbd | |
Bryan Helmkamp | 987766b10d | |
Bryan Helmkamp | 29186616f5 | |
Bryan Helmkamp | 796318d1ed | |
Bryan Helmkamp | 8a81f16e44 | |
Bryan Helmkamp | 273e8c541a | |
Brian Landau | dd98b33713 | |
Brian Landau | 7f36cf472a | |
Bryan Helmkamp | 11996a15dc | |
Simon Rozet | 195f9c3544 | |
Simon Rozet | 0a2b77c9c4 | |
Simon Rozet | 6cda9c79b4 | |
Simon Rozet | 3760867d0f | |
Simon Rozet | f2882ef8b2 | |
Simon Rozet | a5a91b32e9 | |
Simon Rozet | 051dfe188c | |
Simon Rozet | 042268c6a6 | |
Simon Rozet | f2b3b9891b | |
Damian Janowski | cbc447223c | |
Simon Rozet | cf8d891302 | |
Simon Rozet | 4c010d1c65 | |
Simon Rozet | 8cda77318c | |
Simon Rozet | 92ec1c3d92 | |
Simon Rozet | 0a3b979772 | |
Simon Rozet | 3e7886ecab | |
Bryan Helmkamp | 5eeceff9e8 | |
Ryan Carver | c11f4868a9 | |
Bryan Helmkamp | 1769075c25 | |
Bryan Helmkamp | 28f19616d6 | |
Mike Gaffney | 9b5b9fad62 | |
Mike Gaffney | 0c9944c4d8 | |
Bryan Helmkamp | 9a42304513 | |
Bryan Helmkamp | b4ae28c48c | |
Bryan Helmkamp | 953d35b65a | |
Bryan Helmkamp | ae6e3dbfc1 | |
Bryan Helmkamp | d9de87c41f | |
Bryan Helmkamp | 9b971a15c0 | |
Bryan Helmkamp | 6720bbb476 | |
Bryan Helmkamp | 1b5cf4b0e6 | |
Bryan Helmkamp | a015931578 | |
Mike Gaffney | a0b10d9916 | |
Mike Gaffney | 4cce77ef0d | |
Bryan Helmkamp | 45e19867d6 | |
Bryan Helmkamp | f8af783185 | |
Bryan Helmkamp | c2409d78a7 | |
Bryan Helmkamp | 6231e6e4d1 | |
Bryan Helmkamp | d620e66bd8 | |
Bryan Helmkamp | d60671cd3d | |
Bryan Helmkamp | 3bc2d4d1b8 | |
Jakub Kuźma | 8b98540aef | |
Erin Staniland | b75ff6221b | |
Bryan Helmkamp | 78a23abb6e | |
Mike Gaffney | f4141f787d | |
Michael Fellinger | 8d2c027089 | |
Michael Fellinger | 520081c93e | |
Michael Fellinger | 48a4ec905e | |
Michael Fellinger | 9134b09b87 | |
Mike Gaffney | 6bfdcc54cc | |
Mike Gaffney | dd8688f371 | |
Mike Gaffney | 1910204974 | |
Mike Gaffney | 70fadbe7fc | |
Mike Gaffney | 6d74cd935e | |
Mike Gaffney | a6a4a7cfd9 | |
Mike Gaffney | 6816c46d47 | |
Mike Gaffney | f3a12adaa9 | |
Mike Gaffney | e46df8c6f9 | |
Mike Gaffney | 977f643dca | |
Mike Gaffney | abac2023bc | |
mike.gaffney | b2c423c49c | |
mike.gaffney | 796ede6cea | |
mike.gaffney | 28c676b4fc | |
Thomas Jack | 4daf037146 | |
Thomas Jack | 2ae14f78b1 | |
Thomas Jack | 57326e5846 | |
mike.gaffney | f8f254d517 | |
mike.gaffney | bd1655c8e2 | |
mike.gaffney | 2704609224 | |
mike.gaffney | 2219ab62d3 | |
mike.gaffney | 5430930bac | |
mike.gaffney | b6d26480ea | |
mike.gaffney | b85aacae1c | |
mike.gaffney | 0394a1fc15 | |
Matthias Marschall | 9b85b6d7e0 | |
Matthias Marschall | 6cd734aec9 | |
Matthias Marschall | 73dc59cc29 | |
mike.gaffney | 6fc6530a6b | |
Josh Lubaway | 846a90e561 | |
Larry Diehl | 4d05a2cf2b | |
Larry Diehl | 627913708c | |
mike.gaffney | c3f067b551 | |
mike.gaffney | e0bdab3236 | |
mike.gaffney | f6b0a763a0 | |
Piers Cawley | 58601c4653 | |
Thomas Jack | 956b43d72c | |
mike.gaffney | fd431f2ce8 | |
Mike Gaffney | c6fd28d37a | |
Mike Gaffney | f342142a71 | |
Mike Gaffney | fa3b2c8bb2 | |
Luke Amdor | 7f13a70b4b | |
Thomas Jack | 232ed36379 | |
Thomas Jack | db9c5bdc77 | |
snusnu | 77168fd29d | |
snusnu | 926bcc6c66 | |
snusnu | bfa250e7af | |
Bryan Helmkamp | 77fa1bcdb6 | |
Bryan Helmkamp | 7b6b3168a2 | |
Bryan Helmkamp | b439d7f807 | |
Thomas Jack | 8bedf2235d | |
Bryan Helmkamp | 453cb4b3eb | |
Bryan Helmkamp | 3e71ae3733 | |
Bryan Helmkamp | 35cbfd9643 | |
Bryan Helmkamp | b5254109f1 | |
Bryan Helmkamp | 755cf6e508 | |
Thomas Jack | 9a3668be92 | |
David Chelimsky | ffb56aab90 | |
Mutwin Kraus | eddd979361 | |
Ryan Carver | 1a110fe908 | |
Ryan Carver | 26edfbc7cb | |
Ryan Carver | 09509025c3 | |
mike.gaffney | 481bfe03c0 | |
mike.gaffney | 7d4a2035f7 | |
mike.gaffney | b1dfc1c01f | |
Zach Dennis | 7c08390bb8 | |
Noah Davis | ff42db076f | |
Bryan Helmkamp | 03914fd293 | |
Bryan Helmkamp | f3f81dabdc | |
Bryan Helmkamp | b69b4acec4 | |
Bryan Helmkamp | 6697ecd2d3 | |
Bryan Helmkamp | 5bb587dde1 | |
Bryan Helmkamp | 996484c890 | |
Bryan Helmkamp | 979418e303 | |
Bryan Helmkamp | 644478f6f0 | |
Bryan Helmkamp | 50d8a7ec51 | |
Bryan Helmkamp | 91ea8cfa54 | |
Bryan Helmkamp | 304baeb754 | |
Bryan Helmkamp | aa9049953d | |
Balint Erdi | cd49c2d939 | |
pivotal | 0fe3998f64 | |
Bryan Helmkamp | e2a672a767 | |
Andrew Premdas | 742db2d910 | |
Mark Menard | 0c2261d869 | |
Mark Menard | 73f4c441c1 | |
Bryan Helmkamp | 62491121c1 | |
Bryan Helmkamp | d1a2c80ab8 | |
Simon Rozet | 90baf3311c | |
Bryan Helmkamp | 5dc24c613e | |
Mark Menard | c647ae98bb | |
Luke Melia | 72123c1cec | |
Matthew Ford | 740bb293e3 | |
Simon Rozet | 4e07f5b654 | |
Simon Rozet | 7d7c32256d | |
Bryan Helmkamp | 00433bafe5 | |
Bryan Helmkamp | 4115c99c9b | |
Bryan Helmkamp | b7e0d6f8e6 | |
Bryan Helmkamp | e32a208b7f | |
Bryan Helmkamp | aec889a14d | |
Bryan Helmkamp | dad3da195c | |
Bryan Helmkamp | 18c60f4e51 | |
Bryan Helmkamp | 29c40bd73c | |
Bryan Helmkamp | 1625e3e9ba | |
Bryan Helmkamp | a688c28b19 | |
Bryan Helmkamp | 9761b64b60 | |
Bryan Helmkamp | 66d39b851c | |
Bryan Helmkamp | 2296cadb93 | |
Corey Donohoe | 120a53dced | |
Bryan Helmkamp | d96899be8c | |
Corey Donohoe | ec06c76b91 | |
Corey Donohoe | 92565d3bc4 | |
Bryan Helmkamp | b4687c29d5 | |
Bryan Helmkamp | 17a8bc7b66 | |
Bryan Helmkamp | 932fdab884 | |
Bryan Helmkamp | 7ba620f38b | |
Corey Donohoe | 4fb9406154 | |
Corey Donohoe | 63337d4476 | |
Corey Donohoe | 69dfa5022a | |
Corey Donohoe | 7692930769 | |
Corey Donohoe | 9066d2a9cd | |
Corey Donohoe | 4bf49a5163 | |
Corey Donohoe | 8fbcbef180 | |
Corey Donohoe | 82eabc31ee | |
Peter Jaros | 24eab77ecd | |
Bryan Helmkamp | 7fe667da73 | |
Bryan Helmkamp | a89e3ee612 | |
Bryan Helmkamp | 7fc6a79bee | |
Bryan Helmkamp | e97f7fafc5 | |
Bryan Helmkamp | 4769a5f90b | |
Bryan Helmkamp | e5ae16367c | |
Bryan Helmkamp | d9de0c4e78 | |
Bryan Helmkamp | aa97b063f7 | |
Lee Bankewitz | 56e6d15811 | |
T.J. VanSlyke | ea8e1910d1 | |
Noah Davis | 49e86d103f | |
Bryan Helmkamp | c25885afc0 | |
Bryan Helmkamp | 7f9df54838 | |
Bryan Helmkamp | d2d8de7963 | |
Bryan Helmkamp | 91edb22b81 | |
Bryan Helmkamp | 33509ef575 | |
Bryan Helmkamp | 238bfb469e | |
Bryan Helmkamp | 0039bf4d4b | |
Bryan Helmkamp | 6836115308 | |
Mike Gaffney | 3d5dd1343c | |
Mike Gaffney | 8d9d907e73 | |
Noah Davis | f956bea7dd | |
Mike Gaffney | 18fa3ab11c | |
Amos King | 40280a4a0d | |
Mike Gaffney | fc4ba75e22 | |
Amos King | 099341cede | |
Mike Gaffney | f4f0e3b6a7 | |
Amos King | 483559f279 | |
Amos King | 0a021059d6 | |
Amos King | 6e7609e01c | |
Amos King | 118b522662 | |
Amos King | 3a5d34e759 | |
Amos King | 5a91f10a99 | |
Amos King | 0b8e378fb2 | |
Amos King | 5b8e451272 | |
mike.gaffney | cbddebd01c | |
Amos King | a1ef306838 | |
Noah Davis | 996eedb0d2 | |
Amos King | 8c0facc5af | |
Amos King | 813adcc238 | |
Amos King | da59584cdf | |
Amos King | 2c9b546a83 | |
Zach Dennis | 0272e81847 | |
Josh Knowles | 7a59353c78 | |
Adam Greene | 4fc2b7eb7e | |
Adam Greene | 4e3cf59920 | |
Adam Greene | ce36e5890f | |
Bryan Helmkamp | c06fa90864 | |
Bryan Helmkamp | e53c64f763 | |
Bryan Helmkamp | 9a2302e9af | |
Bryan Helmkamp | d60f524df1 | |
Bryan Helmkamp | 0204c2766d | |
Bryan Helmkamp | d64bba627e | |
ichverstehe | 1bfe7634f8 | |
Kyle Hargraves | 6529a016d1 | |
Bryan Helmkamp | 14d114ce1d | |
Bryan Helmkamp | ced63f6e5a | |
Bryan Helmkamp | b8b4a614c4 | |
Amos King | 652610381a | |
Amos King | fd860a2e6d | |
Amos King | a32ec70d7f | |
Amos King | 647eb4cb6f | |
Amos King | 2d065e8a2d | |
Amos King | 0aa5fda61d | |
Amos King | 2510e7d43d | |
Amos King | 3902573d3e | |
Amos King | 9745673f1c | |
Amos King | cdd390a19d | |
Amos King | a396758da4 | |
Mike Gaffney | 758e323f89 | |
Mike Gaffney | c0220232c7 | |
Mike Gaffney | c1b49f36ea | |
Mike Gaffney | 86089d90b6 | |
Mike Gaffney | f7f8c91cb7 | |
Mike Gaffney | f2a202ae5e | |
Mike Gaffney | f835bac31b | |
Mike Gaffney | bdf660aecb | |
Mike Gaffney | a8a63472bc | |
Lena | b4d85cb50b |
|
@ -12,3 +12,7 @@ log
|
||||||
results
|
results
|
||||||
test_apps
|
test_apps
|
||||||
*.tmproj
|
*.tmproj
|
||||||
|
*.log
|
||||||
|
*.pid
|
||||||
|
bin
|
||||||
|
vendor/gems
|
||||||
|
|
|
@ -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"
|
213
History.txt
213
History.txt
|
@ -1,3 +1,216 @@
|
||||||
|
== 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
|
||||||
|
|
||||||
|
* Don't require rubygems at runtime (Simon Rozet)
|
||||||
|
|
||||||
|
== 0.4.5 / 2009-08-10
|
||||||
|
|
||||||
|
* Major enhancements
|
||||||
|
|
||||||
|
* Ruby 1.9 compatibility (Michael Fellinger, Jakub Kuźma)
|
||||||
|
* Improve performance (~2x) on JRuby by supporting Nokogiri
|
||||||
|
* Added support for external app servers in selenium mode (basically don't start one) (Mike Gaffney)
|
||||||
|
* Added support for uploading files for Merb (Ryan Carver)
|
||||||
|
|
||||||
|
* Minor enhancements
|
||||||
|
|
||||||
|
* Upgrade to selenium-client to 1.2.16 (Brian Landau)
|
||||||
|
* Upgrade selenium-server.jar to 1.0.1 (Brian Landau)
|
||||||
|
* Make redirect detection work in the face of rational maths (like when ruby-units is active) (Piers Cawley)
|
||||||
|
* Use Launchy to handle opening pages in the browser with cross-platform compatibility (Bryan Helmkamp)
|
||||||
|
* Added support for field_labeled_locators ending in non word characters
|
||||||
|
lh 148 (Zach Dennis)
|
||||||
|
* Filled in tests on click link lh 195 (diabolo)
|
||||||
|
* Added current_url to selenium session lh 215 (Luke Amdor)
|
||||||
|
* Added silence spec to selenium lh 238 (Martin Gamsjaeger aka snusnu)
|
||||||
|
* Added ability to configure the browser startup timeout for selenium lh 242 (Mike Gaffney, Mark Dodwell)
|
||||||
|
* Added delegation for field_named lh194 (pivotal labs)
|
||||||
|
* Added fix to keep from escaping field values in mechanize mode lh256 (jish)
|
||||||
|
* Adding fixes for click button/link and made the integration specs pass for the same in selenium lh254 (Ldiehl, Matthias Marschall)
|
||||||
|
* Adding clicking link by id in selenium mode lh221 (larrytheliquid)
|
||||||
|
* Adding fix for have_selector and have_xpath in descendent blocks lh234 (Thomas Jack)
|
||||||
|
* Adding fix for fields with labels with special characters (Thomas Jack, Mike Gaffney, Bryan Hemlkamp)
|
||||||
|
* Deprecated current_page lh50 (Mike Gaffney)
|
||||||
|
* Fixed issue with redirects and multiple hosts lh168 (Mutwin Kraus)
|
||||||
|
|
||||||
|
* Bug fixes
|
||||||
|
|
||||||
|
* Wait for application servers socket on 0.0.0.0 instead of the application_address
|
||||||
|
* Translate CSS and image paths with single quotes in save_and_open_page (Erin Staniland)
|
||||||
|
|
||||||
|
== 0.4.4 / 2009-04-06
|
||||||
|
|
||||||
|
* Major enhancements
|
||||||
|
|
||||||
|
* Make selenium process management code more robust and informative
|
||||||
|
|
||||||
|
* Minor enhancements
|
||||||
|
|
||||||
|
* Add support for Rails javascript post links (Mark Menard)
|
||||||
|
* Upgrade selenium-client dependency to 1.2.14, and update for new waiting
|
||||||
|
API (Balint Erdi)
|
||||||
|
* Change default app environment from "selenium" to "test"
|
||||||
|
|
||||||
|
* Bug fixes
|
||||||
|
|
||||||
|
* Don't create a new instance of WWW::Mechanize for each request
|
||||||
|
(Mark Menard)
|
||||||
|
* Select fields with duplicate selected options sent an incorrect value (Noah Davis)
|
||||||
|
|
||||||
|
== 0.4.3 / 2009-03-17
|
||||||
|
|
||||||
|
* Minor enhancements
|
||||||
|
|
||||||
|
* Support Rails 2.3. Use Rack::Utils to parse params (Matthew Ford)
|
||||||
|
* Support for "modular" Sinatra app style (Simon Rozet)
|
||||||
|
* Initial Merb and Sinatra compatibility for Selenium mode (Corey Donohoe)
|
||||||
|
* When faced with a label with no for attribute, that contains a hidden field
|
||||||
|
and another field, as can be the case in Rails 2.3's checkbox view,
|
||||||
|
webrat now locates the non-hidden field. (Luke Melia)
|
||||||
|
* Add application_framework config for Selenium mode to determine how to
|
||||||
|
start and stop the app server (Corey Donohoe)
|
||||||
|
|
||||||
|
* Bug fixes
|
||||||
|
|
||||||
|
* Fix following of absolute redirect URL in Sinatra (Simon Rozet)
|
||||||
|
|
||||||
|
== 0.4.2 / 2009-02-24
|
||||||
|
|
||||||
|
* Major enhancements
|
||||||
|
|
||||||
|
* Significant improvements to have_selector. It now supports specifying
|
||||||
|
attributes in a hash and :count and :content options. See
|
||||||
|
have_selector_spec.rb for more.
|
||||||
|
* Add the same functionality mentioned above to have_xpath
|
||||||
|
|
||||||
|
* Minor enhancements
|
||||||
|
|
||||||
|
* Squeeze extra whitespace out of failures messages from contain
|
||||||
|
matcher
|
||||||
|
* Detect infinite redirects and raise a Webrat::InfiniteRedirectError
|
||||||
|
(Daniel Lucraft)
|
||||||
|
|
||||||
|
* Bug fixes
|
||||||
|
|
||||||
|
* Properly quote single and double quotes strings in XPath
|
||||||
|
* Fix warning caused by Nokogiri deprecating CSS::Parser.parse
|
||||||
|
(Aaron Patterson)
|
||||||
|
* Accept do/end blocks in matchers. [#157] (Peter Jaros)
|
||||||
|
* Quote --chdir option to mongrel_rails to support RAILS_ROOTs with spaces
|
||||||
|
(T.J. VanSlyke)
|
||||||
|
|
||||||
|
== 0.4.1 / 2009-01-31
|
||||||
|
|
||||||
|
* Minor enhancements
|
||||||
|
|
||||||
|
* Support Sinatra 0.9 (Harry Vangberg)
|
||||||
|
* Update query param parsing to work with latest Edge Rails
|
||||||
|
* Added #redirected_to method to easily check where an external redirect was
|
||||||
|
redirected to (Adam Greene)
|
||||||
|
* Recognize input tags with type button (Lena Herrmann)
|
||||||
|
* Add uncheck method to Selenium mode (Lee Bankewitz)
|
||||||
|
|
||||||
|
* Bug fixes
|
||||||
|
|
||||||
|
* Make requests to a Rails app using a full URL instead of a relative path. This change
|
||||||
|
is helpful for Rails apps that use subdomains. (John Hwang and Zach Dennis)
|
||||||
|
* Follow redirects that are on the same domain but a different subdomain
|
||||||
|
(Adam Greene)
|
||||||
|
* rescue from Webrat::TimeoutError in selenium matchers which allows NegativeMatchers
|
||||||
|
to behave correctly (Noah Davis)
|
||||||
|
* Switch to using selenium.click instead of .check when checking a checkbox
|
||||||
|
(Noah Davis)
|
||||||
|
* Create tmp/pids directory if directory does not exist. (Amos King and Mike Gaffney)
|
||||||
|
* Setup deprecated writers for the selenium_environment= and selenium_port= config
|
||||||
|
* Ensure the previous pages params aren't passed through redirect (Daniel Lucraft and
|
||||||
|
Bryan Helmkamp)
|
||||||
|
* Labels should only search for fields within the current scope (Kyle Hargraves)
|
||||||
|
|
||||||
== 0.4.0 / 2009-01-18
|
== 0.4.0 / 2009-01-18
|
||||||
|
|
||||||
* _IMPORTANT_ Breaking change:
|
* _IMPORTANT_ Breaking change:
|
||||||
|
|
198
Rakefile
198
Rakefile
|
@ -1,93 +1,67 @@
|
||||||
# require 'rubygems'
|
begin
|
||||||
require "rake/gempackagetask"
|
require 'spec/rake/spectask'
|
||||||
require 'rake/rdoctask'
|
rescue LoadError
|
||||||
require "rake/clean"
|
desc "Run specs"
|
||||||
require 'spec'
|
task(:spec) { $stderr.puts '`gem install rspec` to run specs' }
|
||||||
require 'spec/rake/spectask'
|
else
|
||||||
require 'spec/rake/verify_rcov'
|
desc "Run API and Core specs"
|
||||||
require File.expand_path('./lib/webrat.rb')
|
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"
|
||||||
# Package && release
|
Spec::Rake::SpecTask.new(:rcov) do |t|
|
||||||
##############################################################################
|
t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
|
||||||
spec = Gem::Specification.new do |s|
|
t.spec_files = FileList['spec/public/**/*_spec.rb'] + FileList['spec/private/**/*_spec.rb']
|
||||||
s.name = "webrat"
|
t.rcov = true
|
||||||
s.version = Webrat::VERSION
|
t.rcov_opts = lambda do
|
||||||
s.platform = Gem::Platform::RUBY
|
IO.readlines(File.dirname(__FILE__) + "/spec/rcov.opts").map {|l| l.chomp.split " "}.flatten
|
||||||
s.author = "Bryan Helmkamp"
|
end
|
||||||
s.email = "bryan" + "@" + "brynary.com"
|
|
||||||
s.homepage = "http://github.com/brynary/webrat"
|
|
||||||
s.summary = "Webrat. Ruby Acceptance Testing for Web applications"
|
|
||||||
s.bindir = "bin"
|
|
||||||
s.description = s.summary
|
|
||||||
s.require_path = "lib"
|
|
||||||
s.files = %w(History.txt install.rb MIT-LICENSE.txt README.rdoc Rakefile) + Dir["lib/**/*"] + Dir["vendor/**/*"]
|
|
||||||
|
|
||||||
# rdoc
|
|
||||||
s.has_rdoc = true
|
|
||||||
s.extra_rdoc_files = %w(README.rdoc MIT-LICENSE.txt)
|
|
||||||
|
|
||||||
# Dependencies
|
|
||||||
s.add_dependency "nokogiri", ">= 1.1.0"
|
|
||||||
|
|
||||||
s.rubyforge_project = "webrat"
|
|
||||||
end
|
|
||||||
|
|
||||||
Rake::GemPackageTask.new(spec) do |package|
|
|
||||||
package.gem_spec = spec
|
|
||||||
end
|
|
||||||
|
|
||||||
desc 'Show information about the gem.'
|
|
||||||
task :debug_gem do
|
|
||||||
puts spec.to_ruby
|
|
||||||
end
|
|
||||||
|
|
||||||
CLEAN.include ["pkg", "*.gem", "doc", "ri", "coverage"]
|
|
||||||
|
|
||||||
desc "Upload rdoc to brynary.com"
|
|
||||||
task :publish_rdoc => :docs do
|
|
||||||
sh "scp -r doc/ brynary.com:/apps/uploads/webrat"
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Run API and Core specs"
|
|
||||||
Spec::Rake::SpecTask.new do |t|
|
|
||||||
t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
|
|
||||||
t.spec_files = FileList['spec/public/**/*_spec.rb'] + FileList['spec/private/**/*_spec.rb']
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Run all specs in spec directory with RCov"
|
|
||||||
Spec::Rake::SpecTask.new(:rcov) do |t|
|
|
||||||
t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
|
|
||||||
t.spec_files = FileList['spec/public/**/*_spec.rb'] + FileList['spec/private/**/*_spec.rb']
|
|
||||||
t.rcov = true
|
|
||||||
t.rcov_opts = lambda do
|
|
||||||
IO.readlines(File.dirname(__FILE__) + "/spec/rcov.opts").map {|l| l.chomp.split " "}.flatten
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
RCov::VerifyTask.new(:verify_rcov => :rcov) do |t|
|
desc "Run everything against multiruby"
|
||||||
t.threshold = 96.2 # Make sure you have rcov 0.7 or higher!
|
task :multiruby do
|
||||||
end
|
result = system "multiruby -S rake spec"
|
||||||
|
raise "Multiruby tests failed" unless result
|
||||||
|
result = system "jruby -S rake spec"
|
||||||
|
raise "JRuby tests failed" unless result
|
||||||
|
|
||||||
desc 'Install the package as a gem.'
|
Dir.chdir "spec/integration/rails" do
|
||||||
task :install_gem => [:clean, :package] do
|
result = system "multiruby -S rake test_unit:rails"
|
||||||
gem_filename = Dir['pkg/*.gem'].first
|
raise "Rails integration tests failed" unless result
|
||||||
sh "sudo gem install --local #{gem_filename}"
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Delete generated RDoc"
|
result = system "jruby -S rake test_unit:rails"
|
||||||
task :clobber_docs do
|
raise "Rails integration tests failed" unless result
|
||||||
FileUtils.rm_rf("doc")
|
end
|
||||||
end
|
|
||||||
|
|
||||||
desc "Generate RDoc"
|
Dir.chdir "spec/integration/merb" do
|
||||||
task :docs => :clobber_docs do
|
result = system "multiruby -S rake spec"
|
||||||
system "hanna --title 'Webrat #{Webrat::VERSION} API Documentation'"
|
raise "Merb integration tests failed" unless result
|
||||||
end
|
|
||||||
|
|
||||||
desc "Run specs using jruby"
|
result = system "jruby -S rake spec"
|
||||||
task "spec:jruby" do
|
raise "Rails integration tests failed" unless result
|
||||||
system "jruby -S rake spec"
|
end
|
||||||
|
|
||||||
|
Dir.chdir "spec/integration/sinatra" do
|
||||||
|
result = system "multiruby -S rake test"
|
||||||
|
raise "Sinatra integration tests failed" unless result
|
||||||
|
|
||||||
|
result = system "jruby -S rake test"
|
||||||
|
raise "Sinatra integration tests failed" unless result
|
||||||
|
end
|
||||||
|
|
||||||
|
Dir.chdir "spec/integration/rack" do
|
||||||
|
result = system "multiruby -S rake test"
|
||||||
|
raise "Rack integration tests failed" unless result
|
||||||
|
|
||||||
|
result = system "jruby -S rake test"
|
||||||
|
raise "Rack integration tests failed" unless result
|
||||||
|
end
|
||||||
|
|
||||||
|
puts
|
||||||
|
puts "Multiruby OK!"
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Run each spec in isolation to test for dependency issues"
|
desc "Run each spec in isolation to test for dependency issues"
|
||||||
|
@ -99,27 +73,38 @@ task :spec_deps do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
task :prepare do
|
|
||||||
system "ln -s ../../../../.. ./spec/integration/rails/vendor/plugins/webrat"
|
|
||||||
end
|
|
||||||
|
|
||||||
namespace :spec do
|
namespace :spec do
|
||||||
desc "Run the integration specs"
|
desc "Run the integration specs"
|
||||||
task :integration => ["integration:rails", "integration:merb", "integration:sinatra"]
|
task :integration => [
|
||||||
|
"integration:rack",
|
||||||
|
"integration:sinatra",
|
||||||
|
"integration:merb",
|
||||||
|
"integration:mechanize",
|
||||||
|
"integration:rails:webrat",
|
||||||
|
"integration:rails:selenium",
|
||||||
|
]
|
||||||
|
|
||||||
namespace :integration do
|
namespace :integration do
|
||||||
desc "Run the Rails integration specs"
|
namespace :rails do
|
||||||
task :rails do
|
task :selenium do
|
||||||
Dir.chdir "spec/integration/rails" do
|
Dir.chdir "spec/integration/rails" do
|
||||||
result = system "rake test:integration"
|
result = system "rake -rubygems test_unit:selenium"
|
||||||
raise "Rails integration tests failed" unless result
|
raise "Rails integration tests failed" unless result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
task :webrat do
|
||||||
|
Dir.chdir "spec/integration/rails" do
|
||||||
|
result = system "rake -rubygems test_unit:rails"
|
||||||
|
raise "Rails integration tests failed" unless result
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Run the Merb integration specs"
|
desc "Run the Merb integration specs"
|
||||||
task :merb do
|
task :merb do
|
||||||
Dir.chdir "spec/integration/merb" do
|
Dir.chdir "spec/integration/merb" do
|
||||||
result = system "rake spec"
|
result = system "rake -rubygems spec"
|
||||||
raise "Merb integration tests failed" unless result
|
raise "Merb integration tests failed" unless result
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -127,13 +112,32 @@ namespace :spec do
|
||||||
desc "Run the Sinatra integration specs"
|
desc "Run the Sinatra integration specs"
|
||||||
task :sinatra do
|
task :sinatra do
|
||||||
Dir.chdir "spec/integration/sinatra" do
|
Dir.chdir "spec/integration/sinatra" do
|
||||||
result = system "rake test"
|
result = system "rake -rubygems test"
|
||||||
raise "Sinatra tntegration tests failed" unless result
|
raise "Sinatra integration tests failed" unless result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Run the Sinatra integration specs"
|
||||||
|
task :rack do
|
||||||
|
Dir.chdir "spec/integration/rack" do
|
||||||
|
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
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
task :default => :spec
|
desc 'Removes trailing whitespace'
|
||||||
|
task :whitespace do
|
||||||
|
sh %{find . -name '*.rb' -exec sed -i '' 's/ *$//g' {} \\;}
|
||||||
|
end
|
||||||
|
|
||||||
task :precommit => ["spec", "spec:jruby", "spec:integration"]
|
task :default => :spec
|
||||||
|
|
|
@ -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
|
|
@ -1,34 +1,18 @@
|
||||||
require "rubygems"
|
require "rack"
|
||||||
|
require "nokogiri"
|
||||||
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
|
|
||||||
|
|
||||||
module Webrat
|
module Webrat
|
||||||
|
VERSION = "0.7.2.pre"
|
||||||
|
|
||||||
|
autoload :MechanizeAdapter, "webrat/adapters/mechanize"
|
||||||
|
autoload :MerbAdapter, "webrat/adapters/merb"
|
||||||
|
autoload :RackAdapter, "webrat/adapters/rack"
|
||||||
|
autoload :RailsAdapter, "webrat/adapters/rails"
|
||||||
|
autoload :SinatraAdapter, "webrat/adapters/sinatra"
|
||||||
|
|
||||||
# The common base class for all exceptions raised by Webrat.
|
# The common base class for all exceptions raised by Webrat.
|
||||||
class WebratError < StandardError
|
class WebratError < StandardError
|
||||||
end
|
end
|
||||||
|
|
||||||
VERSION = '0.4.0'
|
|
||||||
|
|
||||||
def self.require_xml
|
|
||||||
gem "nokogiri", ">= 1.0.6"
|
|
||||||
|
|
||||||
if on_java?
|
|
||||||
# We need Nokogiri's CSS to XPath support, even if using REXML and Hpricot for parsing and searching
|
|
||||||
require "nokogiri/css"
|
|
||||||
require "hpricot"
|
|
||||||
require "rexml/document"
|
|
||||||
else
|
|
||||||
require "nokogiri"
|
|
||||||
require "webrat/core/xml/nokogiri"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.on_java?
|
|
||||||
RUBY_PLATFORM =~ /java/
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
Webrat.require_xml
|
|
||||||
|
|
||||||
require "webrat/core"
|
require "webrat/core"
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
require "mechanize"
|
require "mechanize"
|
||||||
|
|
||||||
module Webrat #:nodoc:
|
module Webrat #:nodoc:
|
||||||
class MechanizeSession < Session #:nodoc:
|
class MechanizeAdapter #:nodoc:
|
||||||
|
extend Forwardable
|
||||||
|
|
||||||
|
Mechanize = WWW::Mechanize if defined?(WWW::Mechanize)
|
||||||
|
|
||||||
attr_accessor :response
|
attr_accessor :response
|
||||||
alias :page :response
|
alias :page :response
|
||||||
|
|
||||||
|
def initialize(*args)
|
||||||
|
end
|
||||||
|
|
||||||
def request_page(url, http_method, data) #:nodoc:
|
def request_page(url, http_method, data) #:nodoc:
|
||||||
super(absolute_url(url), http_method, data)
|
super(absolute_url(url), http_method, data)
|
||||||
end
|
end
|
||||||
|
@ -16,13 +22,19 @@ module Webrat #:nodoc:
|
||||||
|
|
||||||
def post(url, data, headers_argument_not_used = nil)
|
def post(url, data, headers_argument_not_used = nil)
|
||||||
post_data = data.inject({}) do |memo, param|
|
post_data = data.inject({}) do |memo, param|
|
||||||
case param.last
|
case param
|
||||||
when Hash
|
when Hash
|
||||||
param.last.each {|attribute, value| memo["#{param.first}[#{attribute}]"] = value }
|
param.each {|attribute, value| memo[attribute] = value }
|
||||||
else
|
memo
|
||||||
memo[param.first] = param.last
|
when Array
|
||||||
|
case param.last
|
||||||
|
when Hash
|
||||||
|
param.last.each {|attribute, value| memo["#{param.first}[#{attribute}]"] = value }
|
||||||
|
else
|
||||||
|
memo[param.first] = param.last
|
||||||
|
end
|
||||||
|
memo
|
||||||
end
|
end
|
||||||
memo
|
|
||||||
end
|
end
|
||||||
@response = mechanize.post(url, post_data)
|
@response = mechanize.post(url, post_data)
|
||||||
end
|
end
|
||||||
|
@ -35,8 +47,16 @@ module Webrat #:nodoc:
|
||||||
@response.code.to_i
|
@response.code.to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def response_headers
|
||||||
|
@response.header
|
||||||
|
end
|
||||||
|
|
||||||
def mechanize
|
def mechanize
|
||||||
@mechanize = WWW::Mechanize.new
|
@mechanize ||= begin
|
||||||
|
mechanize = Mechanize.new
|
||||||
|
mechanize.redirect_ok = false
|
||||||
|
mechanize
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def_delegators :mechanize, :basic_auth
|
def_delegators :mechanize, :basic_auth
|
||||||
|
@ -67,7 +87,7 @@ module Webrat #:nodoc:
|
||||||
else
|
else
|
||||||
current_path.split("/")[0..(-1 - levels_up)].join("/")
|
current_path.split("/")[0..(-1 - levels_up)].join("/")
|
||||||
end
|
end
|
||||||
descendent = url.split("/")[levels_up..-1]
|
descendent = url.split("/")[levels_up..-1].join
|
||||||
"#{ancestor}/#{descendent}"
|
"#{ancestor}/#{descendent}"
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -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
|
|
@ -0,0 +1,29 @@
|
||||||
|
require "rack/test"
|
||||||
|
|
||||||
|
module Webrat
|
||||||
|
class RackAdapter
|
||||||
|
extend Forwardable
|
||||||
|
|
||||||
|
def_delegators :@session, :get, :post, :put, :delete
|
||||||
|
|
||||||
|
def initialize(session) #:nodoc:
|
||||||
|
@session = session
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_body
|
||||||
|
response.body
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_code
|
||||||
|
response.status
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_headers
|
||||||
|
response.headers
|
||||||
|
end
|
||||||
|
|
||||||
|
def response
|
||||||
|
@session.last_response
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,34 +1,14 @@
|
||||||
require "webrat"
|
require "webrat/integrations/rails"
|
||||||
|
|
||||||
require "action_controller"
|
|
||||||
require "action_controller/integration"
|
|
||||||
require "action_controller/record_identifier"
|
require "action_controller/record_identifier"
|
||||||
|
|
||||||
module Webrat
|
module Webrat
|
||||||
class RailsSession < Session #:nodoc:
|
class RailsAdapter #:nodoc:
|
||||||
include ActionController::RecordIdentifier
|
include ActionController::RecordIdentifier
|
||||||
|
|
||||||
# The Rails version of within supports passing in a model and Webrat
|
attr_reader :integration_session
|
||||||
# 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
|
def initialize(session)
|
||||||
File.expand_path(File.join(RAILS_ROOT, 'public'))
|
@integration_session = session
|
||||||
end
|
|
||||||
|
|
||||||
def saved_page_dir
|
|
||||||
File.expand_path(File.join(RAILS_ROOT, "tmp"))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def get(url, data, headers = nil)
|
def get(url, data, headers = nil)
|
||||||
|
@ -55,16 +35,16 @@ module Webrat
|
||||||
response.code.to_i
|
response.code.to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def response_headers
|
||||||
|
response.headers
|
||||||
|
end
|
||||||
|
|
||||||
def xml_content_type?
|
def xml_content_type?
|
||||||
response.headers["Content-Type"].to_s =~ /xml/
|
response.headers["Content-Type"].to_s =~ /xml/
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def integration_session
|
|
||||||
@context
|
|
||||||
end
|
|
||||||
|
|
||||||
def do_request(http_method, url, data, headers) #:nodoc:
|
def do_request(http_method, url, data, headers) #:nodoc:
|
||||||
update_protocol(url)
|
update_protocol(url)
|
||||||
integration_session.send(http_method, normalize_url(url), data, headers)
|
integration_session.send(http_method, normalize_url(url), data, headers)
|
||||||
|
@ -73,11 +53,13 @@ module Webrat
|
||||||
# remove protocol, host and anchor
|
# remove protocol, host and anchor
|
||||||
def normalize_url(href) #:nodoc:
|
def normalize_url(href) #:nodoc:
|
||||||
uri = URI.parse(href)
|
uri = URI.parse(href)
|
||||||
normalized_url = uri.path
|
normalized_url = []
|
||||||
if uri.query
|
normalized_url << "#{uri.scheme}://" if uri.scheme
|
||||||
normalized_url += "?" + uri.query
|
normalized_url << uri.host if uri.host
|
||||||
end
|
normalized_url << ":#{uri.port}" if uri.port && ![80,443].include?(uri.port)
|
||||||
normalized_url
|
normalized_url << uri.path if uri.path
|
||||||
|
normalized_url << "?#{uri.query}" if uri.query
|
||||||
|
normalized_url.join
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_protocol(href) #:nodoc:
|
def update_protocol(href) #:nodoc:
|
||||||
|
@ -91,13 +73,5 @@ module Webrat
|
||||||
def response #:nodoc:
|
def response #:nodoc:
|
||||||
integration_session.response
|
integration_session.response
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
module ActionController #:nodoc:
|
|
||||||
IntegrationTest.class_eval do
|
|
||||||
include Webrat::Methods
|
|
||||||
include Webrat::Matchers
|
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -0,0 +1,9 @@
|
||||||
|
module Webrat
|
||||||
|
class SinatraAdapter < RackAdapter
|
||||||
|
def initialize(context)
|
||||||
|
app = context.respond_to?(:app) ? context.app : Sinatra::Application
|
||||||
|
|
||||||
|
super(Rack::Test::Session.new(Rack::MockSession.new(app, "www.example.com")))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +1,5 @@
|
||||||
require "webrat/core/configuration"
|
require "webrat/core/configuration"
|
||||||
require "webrat/core/xml"
|
require "webrat/core/xml"
|
||||||
require "webrat/core/xml/nokogiri"
|
|
||||||
require "webrat/core/logging"
|
require "webrat/core/logging"
|
||||||
require "webrat/core/elements/form"
|
require "webrat/core/elements/form"
|
||||||
require "webrat/core/scope"
|
require "webrat/core/scope"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
require "webrat/core_extensions/deprecate"
|
require "webrat/core_extensions/deprecate"
|
||||||
|
require "pathname"
|
||||||
|
|
||||||
module Webrat
|
module Webrat
|
||||||
|
|
||||||
|
@ -16,26 +17,38 @@ module Webrat
|
||||||
# Webrat can be configured using the Webrat.configure method. For example:
|
# Webrat can be configured using the Webrat.configure method. For example:
|
||||||
#
|
#
|
||||||
# Webrat.configure do |config|
|
# Webrat.configure do |config|
|
||||||
# config.parse_with_nokogiri = false
|
# config.mode = :sinatra
|
||||||
# end
|
# end
|
||||||
class Configuration
|
class Configuration
|
||||||
|
|
||||||
# Should XHTML be parsed with Nokogiri? Defaults to true, except on JRuby. When false, Hpricot and REXML are used
|
|
||||||
attr_writer :parse_with_nokogiri
|
|
||||||
|
|
||||||
# Webrat's mode, set automatically when requiring webrat/rails, webrat/merb, etc.
|
# Webrat's mode, set automatically when requiring webrat/rails, webrat/merb, etc.
|
||||||
attr_reader :mode # :nodoc:
|
attr_reader :mode # :nodoc:
|
||||||
|
|
||||||
# Save and open pages with error status codes (500-599) in a browser? Defualts to true.
|
# Save and open pages with error status codes (500-599) in a browser? Defualts to true.
|
||||||
attr_writer :open_error_files
|
attr_writer :open_error_files
|
||||||
|
|
||||||
# Which rails environment should the selenium tests be run in? Defaults to selenium.
|
# Save and open page storage directory, defaults to "tmp" under current directory if exists, otherwise current directory
|
||||||
|
attr_accessor :saved_pages_dir
|
||||||
|
|
||||||
|
# Which rails environment should the selenium tests be run in? Defaults to test.
|
||||||
attr_accessor :application_environment
|
attr_accessor :application_environment
|
||||||
webrat_deprecate :selenium_environment, :application_environment
|
webrat_deprecate :selenium_environment, :application_environment
|
||||||
|
webrat_deprecate :selenium_environment=, :application_environment=
|
||||||
|
|
||||||
# Which port is the application running on for selenium testing? Defaults to 3001.
|
# Which port is the application running on for selenium testing? Defaults to 3001.
|
||||||
attr_accessor :application_port
|
attr_accessor :application_port
|
||||||
webrat_deprecate :selenium_port, :application_port
|
webrat_deprecate :selenium_port, :application_port
|
||||||
|
webrat_deprecate :selenium_port=, :application_port=
|
||||||
|
|
||||||
|
# Which port should selenium use to access the application. Defaults to application_port
|
||||||
|
attr_writer :application_port_for_selenium
|
||||||
|
|
||||||
|
def application_port_for_selenium
|
||||||
|
@application_port_for_selenium || self.application_port
|
||||||
|
end
|
||||||
|
|
||||||
|
# Which underlying app framework we're testing with selenium
|
||||||
|
attr_accessor :application_framework
|
||||||
|
|
||||||
# Which server the application is running on for selenium testing? Defaults to localhost
|
# Which server the application is running on for selenium testing? Defaults to localhost
|
||||||
attr_accessor :application_address
|
attr_accessor :application_address
|
||||||
|
@ -49,18 +62,34 @@ module Webrat
|
||||||
# Set the key that Selenium uses to determine the browser running. Default *firefox
|
# Set the key that Selenium uses to determine the browser running. Default *firefox
|
||||||
attr_accessor :selenium_browser_key
|
attr_accessor :selenium_browser_key
|
||||||
|
|
||||||
|
# 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:
|
def initialize # :nodoc:
|
||||||
self.open_error_files = true
|
self.open_error_files = true
|
||||||
self.parse_with_nokogiri = !Webrat.on_java?
|
self.application_environment = :test
|
||||||
self.application_environment = :selenium
|
|
||||||
self.application_port = 3001
|
self.application_port = 3001
|
||||||
self.application_address = 'localhost'
|
self.application_address = 'localhost'
|
||||||
|
self.application_framework = :rails
|
||||||
self.selenium_server_port = 4444
|
self.selenium_server_port = 4444
|
||||||
|
self.infinite_redirect_limit = 10
|
||||||
self.selenium_browser_key = '*firefox'
|
self.selenium_browser_key = '*firefox'
|
||||||
end
|
self.selenium_browser_startup_timeout = 5
|
||||||
|
self.selenium_verbose_output = false
|
||||||
|
|
||||||
def parse_with_nokogiri? #:nodoc:
|
tmp_dir = Pathname.new(Dir.pwd).join("tmp")
|
||||||
@parse_with_nokogiri ? true : false
|
self.saved_pages_dir = tmp_dir.exist? ? tmp_dir : Dir.pwd
|
||||||
end
|
end
|
||||||
|
|
||||||
def open_error_files? #:nodoc:
|
def open_error_files? #:nodoc:
|
||||||
|
@ -72,13 +101,11 @@ module Webrat
|
||||||
def mode=(mode)
|
def mode=(mode)
|
||||||
@mode = mode.to_sym
|
@mode = mode.to_sym
|
||||||
|
|
||||||
# This is a temporary hack to support backwards compatibility
|
begin
|
||||||
# with Merb 1.0.8 until it's updated to use the new Webrat.configure
|
require("webrat/integrations/#{mode}")
|
||||||
# syntax
|
rescue LoadError
|
||||||
if @mode == :merb
|
# Only some modes have integration code that needs to
|
||||||
require("webrat/merb_session")
|
# be loaded, so this is OK
|
||||||
else
|
|
||||||
require("webrat/#{mode}")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ module Webrat
|
||||||
class Area < Element #:nodoc:
|
class Area < Element #:nodoc:
|
||||||
|
|
||||||
def self.xpath_search
|
def self.xpath_search
|
||||||
".//area"
|
[".//area"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def click(method = nil, options = {})
|
def click(method = nil, options = {})
|
||||||
|
@ -14,7 +14,7 @@ module Webrat
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def href
|
def href
|
||||||
Webrat::XML.attribute(@element, "href")
|
@element["href"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def absolute_href
|
def absolute_href
|
||||||
|
|
|
@ -3,14 +3,14 @@ module Webrat
|
||||||
class Element # :nodoc:
|
class Element # :nodoc:
|
||||||
|
|
||||||
def self.load_all(session, dom)
|
def self.load_all(session, dom)
|
||||||
Webrat::XML.xpath_search(dom, xpath_search).map do |element|
|
dom.xpath(*xpath_search).map do |element|
|
||||||
load(session, element)
|
load(session, element)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.load(session, element)
|
def self.load(session, element)
|
||||||
return nil if element.nil?
|
return nil if element.nil?
|
||||||
session.elements[Webrat::XML.xpath_to(element)] ||= self.new(session, element)
|
session.elements[element.path] ||= self.new(session, element)
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :element
|
attr_reader :element
|
||||||
|
@ -21,7 +21,7 @@ module Webrat
|
||||||
end
|
end
|
||||||
|
|
||||||
def path
|
def path
|
||||||
Webrat::XML.xpath_to(@element)
|
@element.path
|
||||||
end
|
end
|
||||||
|
|
||||||
def inspect
|
def inspect
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
require "cgi"
|
require "cgi"
|
||||||
|
require "digest/md5"
|
||||||
require "webrat/core_extensions/blank"
|
require "webrat/core_extensions/blank"
|
||||||
require "webrat/core_extensions/nil_to_param"
|
require "webrat/core_extensions/nil_to_query_string"
|
||||||
|
|
||||||
require "webrat/core/elements/element"
|
require "webrat/core/elements/element"
|
||||||
|
|
||||||
|
@ -13,7 +14,11 @@ module Webrat
|
||||||
attr_reader :value
|
attr_reader :value
|
||||||
|
|
||||||
def self.xpath_search
|
def self.xpath_search
|
||||||
[".//button", ".//input", ".//textarea", ".//select"]
|
".//button|.//input|.//textarea|.//select"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.xpath_search_excluding_hidden
|
||||||
|
[".//button", ".//input[ @type != 'hidden']", ".//textarea", ".//select"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.field_classes
|
def self.field_classes
|
||||||
|
@ -28,16 +33,21 @@ module Webrat
|
||||||
|
|
||||||
def self.load(session, element)
|
def self.load(session, element)
|
||||||
return nil if element.nil?
|
return nil if element.nil?
|
||||||
session.elements[Webrat::XML.xpath_to(element)] ||= field_class(element).new(session, element)
|
session.elements[element.path] ||= field_class(element).new(session, element)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.field_class(element)
|
def self.field_class(element)
|
||||||
case element.name
|
case element.name
|
||||||
when "button" then ButtonField
|
when "button" then ButtonField
|
||||||
when "select" then SelectField
|
when "select"
|
||||||
|
if element.attributes["multiple"].nil?
|
||||||
|
SelectField
|
||||||
|
else
|
||||||
|
MultipleSelectField
|
||||||
|
end
|
||||||
when "textarea" then TextareaField
|
when "textarea" then TextareaField
|
||||||
else
|
else
|
||||||
case Webrat::XML.attribute(element, "type")
|
case element["type"]
|
||||||
when "checkbox" then CheckboxField
|
when "checkbox" then CheckboxField
|
||||||
when "hidden" then HiddenField
|
when "hidden" then HiddenField
|
||||||
when "radio" then RadioField
|
when "radio" then RadioField
|
||||||
|
@ -45,6 +55,7 @@ module Webrat
|
||||||
when "file" then FileField
|
when "file" then FileField
|
||||||
when "reset" then ResetField
|
when "reset" then ResetField
|
||||||
when "submit" then ButtonField
|
when "submit" then ButtonField
|
||||||
|
when "button" then ButtonField
|
||||||
when "image" then ButtonField
|
when "image" then ButtonField
|
||||||
else TextField
|
else TextField
|
||||||
end
|
end
|
||||||
|
@ -62,11 +73,11 @@ module Webrat
|
||||||
end
|
end
|
||||||
|
|
||||||
def id
|
def id
|
||||||
Webrat::XML.attribute(@element, "id")
|
@element["id"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def disabled?
|
def disabled?
|
||||||
@element.attributes.has_key?("disabled") && Webrat::XML.attribute(@element, "disabled") != 'false'
|
@element.attributes.has_key?("disabled") && @element["disabled"] != 'false'
|
||||||
end
|
end
|
||||||
|
|
||||||
def raise_error_if_disabled
|
def raise_error_if_disabled
|
||||||
|
@ -74,17 +85,17 @@ module Webrat
|
||||||
raise DisabledFieldError.new("Cannot interact with disabled form element (#{self})")
|
raise DisabledFieldError.new("Cannot interact with disabled form element (#{self})")
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_param
|
def to_query_string
|
||||||
return nil if disabled?
|
return nil if disabled?
|
||||||
|
|
||||||
case Webrat.configuration.mode
|
query_string = case Webrat.configuration.mode
|
||||||
when :rails
|
when :rails, :merb, :rack, :sinatra
|
||||||
rails_request_parser.parse_query_parameters("#{name}=#{escaped_value}")
|
build_query_string
|
||||||
when :merb
|
when :mechanize
|
||||||
::Merb::Parse.query("#{name}=#{escaped_value}")
|
build_query_string(false)
|
||||||
else
|
|
||||||
{ name => escaped_value }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
query_string
|
||||||
end
|
end
|
||||||
|
|
||||||
def set(value)
|
def set(value)
|
||||||
|
@ -97,14 +108,6 @@ module Webrat
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def rails_request_parser
|
|
||||||
if defined?(ActionController::RequestParser) # For Rails > 2.2
|
|
||||||
ActionController::RequestParser
|
|
||||||
else
|
|
||||||
ActionController::AbstractRequest
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def form
|
def form
|
||||||
Form.load(@session, form_element)
|
Form.load(@session, form_element)
|
||||||
end
|
end
|
||||||
|
@ -119,7 +122,19 @@ module Webrat
|
||||||
end
|
end
|
||||||
|
|
||||||
def name
|
def name
|
||||||
Webrat::XML.attribute(@element, "name")
|
@element["name"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_query_string(escape_value=true)
|
||||||
|
if @value.is_a?(Array)
|
||||||
|
@value.collect {|value| "#{name}=#{ escape_value ? escape(value) : value }" }.join("&")
|
||||||
|
else
|
||||||
|
"#{name}=#{ escape_value ? escape(value) : value }"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def escape(value)
|
||||||
|
CGI.escape(value.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
def escaped_value
|
def escaped_value
|
||||||
|
@ -146,40 +161,24 @@ module Webrat
|
||||||
end
|
end
|
||||||
|
|
||||||
unless id.blank?
|
unless id.blank?
|
||||||
@label_elements += Webrat::XML.xpath_search(form.element, ".//label[@for = '#{id}']")
|
@label_elements += form.element.xpath(".//label[@for = '#{id}']")
|
||||||
end
|
end
|
||||||
|
|
||||||
@label_elements
|
@label_elements
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_value
|
def default_value
|
||||||
Webrat::XML.attribute(@element, "value")
|
@element["value"]
|
||||||
end
|
|
||||||
|
|
||||||
def replace_param_value(params, oval, nval)
|
|
||||||
output = Hash.new
|
|
||||||
params.each do |key, value|
|
|
||||||
case value
|
|
||||||
when Hash
|
|
||||||
value = replace_param_value(value, oval, nval)
|
|
||||||
when Array
|
|
||||||
value = value.map { |o| o == oval ? nval : oval }
|
|
||||||
when oval
|
|
||||||
value = nval
|
|
||||||
end
|
|
||||||
output[key] = value
|
|
||||||
end
|
|
||||||
output
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ButtonField < Field #:nodoc:
|
class ButtonField < Field #:nodoc:
|
||||||
|
|
||||||
def self.xpath_search
|
def self.xpath_search
|
||||||
[".//button", ".//input[@type = 'submit']", ".//input[@type = 'image']"]
|
[".//button", ".//input[@type = 'submit']", ".//input[@type = 'button']", ".//input[@type = 'image']"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_param
|
def to_query_string
|
||||||
return nil if @value.nil?
|
return nil if @value.nil?
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
@ -190,7 +189,7 @@ module Webrat
|
||||||
|
|
||||||
def click
|
def click
|
||||||
raise_error_if_disabled
|
raise_error_if_disabled
|
||||||
set(Webrat::XML.attribute(@element, "value")) unless Webrat::XML.attribute(@element, "name").blank?
|
set(@element["value"]) unless @element["name"].blank?
|
||||||
form.submit
|
form.submit
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -202,13 +201,13 @@ module Webrat
|
||||||
".//input[@type = 'hidden']"
|
".//input[@type = 'hidden']"
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_param
|
def to_query_string
|
||||||
if collection_name?
|
if collection_name?
|
||||||
super
|
super
|
||||||
else
|
else
|
||||||
checkbox_with_same_name = form.field_named(name, CheckboxField)
|
checkbox_with_same_name = form.field_named(name, CheckboxField)
|
||||||
|
|
||||||
if checkbox_with_same_name.to_param.blank?
|
if checkbox_with_same_name.to_query_string.blank?
|
||||||
super
|
super
|
||||||
else
|
else
|
||||||
nil
|
nil
|
||||||
|
@ -230,18 +229,18 @@ module Webrat
|
||||||
".//input[@type = 'checkbox']"
|
".//input[@type = 'checkbox']"
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_param
|
def to_query_string
|
||||||
return nil if @value.nil?
|
return nil if @value.nil?
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
def check
|
def check
|
||||||
raise_error_if_disabled
|
raise_error_if_disabled
|
||||||
set(Webrat::XML.attribute(@element, "value") || "on")
|
set(@element["value"] || "on")
|
||||||
end
|
end
|
||||||
|
|
||||||
def checked?
|
def checked?
|
||||||
Webrat::XML.attribute(@element, "checked") == "checked"
|
@element["checked"] == "checked"
|
||||||
end
|
end
|
||||||
|
|
||||||
def uncheck
|
def uncheck
|
||||||
|
@ -252,8 +251,8 @@ module Webrat
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def default_value
|
def default_value
|
||||||
if Webrat::XML.attribute(@element, "checked") == "checked"
|
if @element["checked"] == "checked"
|
||||||
Webrat::XML.attribute(@element, "value") || "on"
|
@element["value"] || "on"
|
||||||
else
|
else
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
@ -275,7 +274,7 @@ module Webrat
|
||||||
".//input[@type = 'radio']"
|
".//input[@type = 'radio']"
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_param
|
def to_query_string
|
||||||
return nil if @value.nil?
|
return nil if @value.nil?
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
@ -286,11 +285,11 @@ module Webrat
|
||||||
option.set(nil)
|
option.set(nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
set(Webrat::XML.attribute(@element, "value") || "on")
|
set(@element["value"] || "on")
|
||||||
end
|
end
|
||||||
|
|
||||||
def checked?
|
def checked?
|
||||||
Webrat::XML.attribute(@element, "checked") == "checked"
|
@element["checked"] == "checked"
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
@ -300,8 +299,8 @@ module Webrat
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_value
|
def default_value
|
||||||
if Webrat::XML.attribute(@element, "checked") == "checked"
|
if @element["checked"] == "checked"
|
||||||
Webrat::XML.attribute(@element, "value") || "on"
|
@element["value"] || "on"
|
||||||
else
|
else
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
@ -318,7 +317,7 @@ module Webrat
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def default_value
|
def default_value
|
||||||
Webrat::XML.inner_html(@element)
|
@element.inner_html
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -332,25 +331,32 @@ module Webrat
|
||||||
attr_accessor :content_type
|
attr_accessor :content_type
|
||||||
|
|
||||||
def set(value, content_type = nil)
|
def set(value, content_type = nil)
|
||||||
|
@original_value = @value
|
||||||
|
@content_type ||= content_type
|
||||||
super(value)
|
super(value)
|
||||||
@content_type = content_type
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_param
|
def digest_value
|
||||||
if @value.nil?
|
@value ? Digest::MD5.hexdigest(self.object_id.to_s) : ""
|
||||||
super
|
|
||||||
else
|
|
||||||
replace_param_value(super, @value, test_uploaded_file)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
def to_query_string
|
||||||
|
@value.nil? ? set("") : set(digest_value)
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
def test_uploaded_file
|
def test_uploaded_file
|
||||||
if content_type
|
return "" if @original_value.blank?
|
||||||
ActionController::TestUploadedFile.new(@value, content_type)
|
|
||||||
else
|
case Webrat.configuration.mode
|
||||||
ActionController::TestUploadedFile.new(@value)
|
when :rails
|
||||||
|
if content_type
|
||||||
|
ActionController::TestUploadedFile.new(@original_value, content_type)
|
||||||
|
else
|
||||||
|
ActionController::TestUploadedFile.new(@original_value)
|
||||||
|
end
|
||||||
|
when :rack, :merb
|
||||||
|
Rack::Test::UploadedFile.new(@original_value, content_type)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -364,31 +370,69 @@ module Webrat
|
||||||
|
|
||||||
class ResetField < Field #:nodoc:
|
class ResetField < Field #:nodoc:
|
||||||
def self.xpath_search
|
def self.xpath_search
|
||||||
".//input[@type = 'reset']"
|
[".//input[@type = 'reset']"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class SelectField < Field #:nodoc:
|
class SelectField < Field #:nodoc:
|
||||||
|
|
||||||
def self.xpath_search
|
def self.xpath_search
|
||||||
".//select"
|
[".//select[not(@multiple)]"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def options
|
def options
|
||||||
@options ||= SelectOption.load_all(@session, @element)
|
@options ||= SelectOption.load_all(@session, @element)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def unset(value)
|
||||||
|
@value = nil
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def default_value
|
def default_value
|
||||||
selected_options = Webrat::XML.xpath_search(@element, ".//option[@selected = 'selected']")
|
selected_options = @element.xpath(".//option[@selected = 'selected']")
|
||||||
selected_options = Webrat::XML.xpath_search(@element, ".//option[position() = 1]") if selected_options.empty?
|
selected_options = @element.xpath(".//option[position() = 1]") if selected_options.empty?
|
||||||
|
|
||||||
selected_options.map do |option|
|
selected_options.map do |option|
|
||||||
return "" if option.nil?
|
return "" if option.nil?
|
||||||
Webrat::XML.attribute(option, "value") || Webrat::XML.inner_html(option)
|
option["value"] || option.inner_html
|
||||||
end
|
end.uniq.first
|
||||||
end
|
end
|
||||||
|
|
||||||
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
|
end
|
||||||
|
|
|
@ -9,7 +9,7 @@ module Webrat
|
||||||
attr_reader :element
|
attr_reader :element
|
||||||
|
|
||||||
def self.xpath_search
|
def self.xpath_search
|
||||||
".//form"
|
[".//form"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def fields
|
def fields
|
||||||
|
@ -27,7 +27,7 @@ module Webrat
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def dom
|
def dom
|
||||||
Webrat::XML.xpath_at(@session.dom, path)
|
@session.dom.xpath(path).first
|
||||||
end
|
end
|
||||||
|
|
||||||
def fields_by_type(field_types)
|
def fields_by_type(field_types)
|
||||||
|
@ -38,66 +38,90 @@ module Webrat
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# iterate over all form fields to build a request querystring to get params from it,
|
||||||
|
# for file_field we made a work around to pass a digest as value to later replace it
|
||||||
|
# in params hash with the real file.
|
||||||
def params
|
def params
|
||||||
all_params = {}
|
query_string = []
|
||||||
|
replaces = {}
|
||||||
|
|
||||||
fields.each do |field|
|
fields.each do |field|
|
||||||
next if field.to_param.nil?
|
next if field.to_query_string.nil?
|
||||||
merge(all_params, field.to_param)
|
replaces.merge!({field.digest_value => field.test_uploaded_file}) if field.is_a?(FileField)
|
||||||
|
query_string << field.to_query_string
|
||||||
end
|
end
|
||||||
|
|
||||||
all_params
|
query_params = self.class.query_string_to_params(query_string.join('&'))
|
||||||
|
|
||||||
|
query_params = self.class.replace_params_values(query_params, replaces)
|
||||||
|
|
||||||
|
self.class.unescape_params(query_params)
|
||||||
end
|
end
|
||||||
|
|
||||||
def form_method
|
def form_method
|
||||||
Webrat::XML.attribute(@element, "method").blank? ? :get : Webrat::XML.attribute(@element, "method").downcase
|
@element["method"].blank? ? :get : @element["method"].downcase
|
||||||
end
|
end
|
||||||
|
|
||||||
def form_action
|
def form_action
|
||||||
Webrat::XML.attribute(@element, "action").blank? ? @session.current_url : Webrat::XML.attribute(@element, "action")
|
@element["action"].blank? ? @session.current_url : @element["action"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def merge(all_params, new_param)
|
def self.replace_param_value(params, oval, nval)
|
||||||
new_param.each do |key, value|
|
output = Hash.new
|
||||||
case all_params[key]
|
params.each do |key, value|
|
||||||
when *hash_classes
|
case value
|
||||||
merge_hash_values(all_params[key], value)
|
when Hash
|
||||||
|
value = replace_param_value(value, oval, nval)
|
||||||
when Array
|
when Array
|
||||||
all_params[key] += value
|
value = value.map { |o| o == oval ? nval : ( o.is_a?(Hash) ? replace_param_value(o, oval, nval) : o) }
|
||||||
else
|
when oval
|
||||||
all_params[key] = value
|
value = nval
|
||||||
end
|
end
|
||||||
|
output[key] = value
|
||||||
|
end
|
||||||
|
output
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.replace_params_values(params, values)
|
||||||
|
values.each do |key, value|
|
||||||
|
params = replace_param_value(params, key, value)
|
||||||
|
end
|
||||||
|
params
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.unescape_params(params)
|
||||||
|
case params.class.name
|
||||||
|
when 'Hash', 'Mash'
|
||||||
|
params.each { |key,value| params[key] = unescape_params(value) }
|
||||||
|
params
|
||||||
|
when 'Array'
|
||||||
|
params.collect { |value| unescape_params(value) }
|
||||||
|
else
|
||||||
|
params.is_a?(String) ? CGI.unescapeHTML(params) : params
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def merge_hash_values(a, b) # :nodoc:
|
def self.query_string_to_params(query_string)
|
||||||
a.keys.each do |k|
|
|
||||||
if b.has_key?(k)
|
|
||||||
case [a[k], b[k]].map{|value| value.class}
|
|
||||||
when *hash_classes.zip(hash_classes)
|
|
||||||
a[k] = merge_hash_values(a[k], b[k])
|
|
||||||
b.delete(k)
|
|
||||||
when [Array, Array]
|
|
||||||
a[k] += b[k]
|
|
||||||
b.delete(k)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
a.merge!(b)
|
|
||||||
end
|
|
||||||
|
|
||||||
def hash_classes
|
|
||||||
klasses = [Hash]
|
|
||||||
|
|
||||||
case Webrat.configuration.mode
|
case Webrat.configuration.mode
|
||||||
when :rails
|
when :rails
|
||||||
klasses << HashWithIndifferentAccess
|
parse_rails_request_params(query_string)
|
||||||
when :merb
|
when :merb
|
||||||
klasses << Mash
|
::Merb::Parse.query(query_string)
|
||||||
|
when :rack, :sinatra
|
||||||
|
Rack::Utils.parse_nested_query(query_string)
|
||||||
|
else
|
||||||
|
Hash[query_string.split('&').map {|query| [ query.split('=').first, query.split('=').last ]}]
|
||||||
end
|
end
|
||||||
|
|
||||||
klasses
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.parse_rails_request_params(query_string)
|
||||||
|
if defined?(ActionController::AbstractRequest)
|
||||||
|
ActionController::AbstractRequest.parse_query_parameters(query_string)
|
||||||
|
elsif defined?(ActionController::UrlEncodedPairParser)
|
||||||
|
ActionController::UrlEncodedPairParser.parse_query_parameters(query_string)
|
||||||
|
else
|
||||||
|
Rack::Utils.parse_nested_query(query_string)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,11 +6,11 @@ module Webrat
|
||||||
attr_reader :element
|
attr_reader :element
|
||||||
|
|
||||||
def self.xpath_search
|
def self.xpath_search
|
||||||
".//label"
|
[".//label"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def for_id
|
def for_id
|
||||||
Webrat::XML.attribute(@element, "for")
|
@element["for"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def field
|
def field
|
||||||
|
@ -21,9 +21,9 @@ module Webrat
|
||||||
|
|
||||||
def field_element
|
def field_element
|
||||||
if for_id.blank?
|
if for_id.blank?
|
||||||
Webrat::XML.xpath_at(@element, *Field.xpath_search)
|
@element.xpath(*Field.xpath_search_excluding_hidden).first
|
||||||
else
|
else
|
||||||
Webrat::XML.css_search(@session.dom, "#" + for_id).first
|
@session.current_dom.css("#" + for_id).first
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
require "webrat/core_extensions/blank"
|
require "English"
|
||||||
|
|
||||||
|
require "webrat/core_extensions/blank"
|
||||||
require "webrat/core/elements/element"
|
require "webrat/core/elements/element"
|
||||||
|
|
||||||
module Webrat
|
module Webrat
|
||||||
class Link < Element #:nodoc:
|
class Link < Element #:nodoc:
|
||||||
|
|
||||||
def self.xpath_search
|
def self.xpath_search
|
||||||
".//a[@href]"
|
[".//a[@href]"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def click(options = {})
|
def click(options = {})
|
||||||
|
@ -25,7 +26,7 @@ module Webrat
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def id
|
def id
|
||||||
Webrat::XML.attribute(@element, "id")
|
@element["id"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def data
|
def data
|
||||||
|
@ -33,11 +34,11 @@ module Webrat
|
||||||
end
|
end
|
||||||
|
|
||||||
def title
|
def title
|
||||||
Webrat::XML.attribute(@element, "title")
|
@element["title"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def href
|
def href
|
||||||
Webrat::XML.attribute(@element, "href")
|
@element["href"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def absolute_href
|
def absolute_href
|
||||||
|
@ -52,12 +53,12 @@ module Webrat
|
||||||
|
|
||||||
def authenticity_token
|
def authenticity_token
|
||||||
return unless onclick && onclick.include?("s.setAttribute('name', 'authenticity_token');") &&
|
return unless onclick && onclick.include?("s.setAttribute('name', 'authenticity_token');") &&
|
||||||
onclick =~ /s\.setAttribute\('value', '([a-f0-9]{40})'\);/
|
( onclick =~ /s\.setAttribute\('value', '([a-f0-9]{40})'\);/ || onclick =~ /s\.setAttribute\('value', '(.{44})'\);/ )
|
||||||
$LAST_MATCH_INFO.captures.first
|
$LAST_MATCH_INFO.captures.first
|
||||||
end
|
end
|
||||||
|
|
||||||
def onclick
|
def onclick
|
||||||
Webrat::XML.attribute(@element, "onclick")
|
@element["onclick"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def http_method
|
def http_method
|
||||||
|
@ -81,6 +82,8 @@ module Webrat
|
||||||
:delete
|
:delete
|
||||||
elsif onclick.include?("m.setAttribute('value', 'put')")
|
elsif onclick.include?("m.setAttribute('value', 'put')")
|
||||||
:put
|
:put
|
||||||
|
elsif onclick.include?("m.setAttribute('value', 'post')")
|
||||||
|
:post
|
||||||
else
|
else
|
||||||
raise Webrat::WebratError.new("No HTTP method for _method param in #{onclick.inspect}")
|
raise Webrat::WebratError.new("No HTTP method for _method param in #{onclick.inspect}")
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@ module Webrat
|
||||||
class SelectOption < Element #:nodoc:
|
class SelectOption < Element #:nodoc:
|
||||||
|
|
||||||
def self.xpath_search
|
def self.xpath_search
|
||||||
".//option"
|
[".//option"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def choose
|
def choose
|
||||||
|
@ -12,6 +12,15 @@ module Webrat
|
||||||
select.set(value)
|
select.set(value)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def unchoose
|
||||||
|
select.raise_error_if_disabled
|
||||||
|
select.unset(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def inner_text
|
||||||
|
@element.inner_text
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def select
|
def select
|
||||||
|
@ -28,7 +37,11 @@ module Webrat
|
||||||
end
|
end
|
||||||
|
|
||||||
def value
|
def value
|
||||||
Webrat::XML.attribute(@element, "value") || Webrat::XML.inner_html(@element)
|
@element["value"] || @element.inner_html
|
||||||
|
end
|
||||||
|
|
||||||
|
def label
|
||||||
|
@element.inner_html
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,7 +13,7 @@ module Webrat
|
||||||
module Locators
|
module Locators
|
||||||
|
|
||||||
def field_by_xpath(xpath)
|
def field_by_xpath(xpath)
|
||||||
Field.load(@session, Webrat::XML.xpath_at(dom, xpath))
|
Field.load(@session, dom.xpath(xpath).first)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,8 +11,8 @@ module Webrat
|
||||||
|
|
||||||
def area_element
|
def area_element
|
||||||
area_elements.detect do |area_element|
|
area_elements.detect do |area_element|
|
||||||
Webrat::XML.attribute(area_element, "title") =~ matcher ||
|
area_element["title"] =~ matcher ||
|
||||||
Webrat::XML.attribute(area_element, "id") =~ matcher
|
area_element["id"] =~ matcher
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ module Webrat
|
||||||
end
|
end
|
||||||
|
|
||||||
def area_elements
|
def area_elements
|
||||||
Webrat::XML.xpath_search(@dom, Area.xpath_search)
|
@dom.xpath(*Area.xpath_search)
|
||||||
end
|
end
|
||||||
|
|
||||||
def error_message
|
def error_message
|
||||||
|
|
|
@ -20,24 +20,24 @@ module Webrat
|
||||||
end
|
end
|
||||||
|
|
||||||
def matches_id?(element)
|
def matches_id?(element)
|
||||||
(@value.is_a?(Regexp) && Webrat::XML.attribute(element, "id") =~ @value) ||
|
(@value.is_a?(Regexp) && element["id"] =~ @value) ||
|
||||||
(!@value.is_a?(Regexp) && Webrat::XML.attribute(element, "id") == @value.to_s)
|
(!@value.is_a?(Regexp) && element["id"] == @value.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
def matches_value?(element)
|
def matches_value?(element)
|
||||||
Webrat::XML.attribute(element, "value") =~ /^\W*#{Regexp.escape(@value.to_s)}/i
|
element["value"] =~ /^\W*#{Regexp.escape(@value.to_s)}/i
|
||||||
end
|
end
|
||||||
|
|
||||||
def matches_html?(element)
|
def matches_html?(element)
|
||||||
Webrat::XML.inner_html(element) =~ /#{Regexp.escape(@value.to_s)}/i
|
element.inner_html =~ /#{Regexp.escape(@value.to_s)}/i
|
||||||
end
|
end
|
||||||
|
|
||||||
def matches_alt?(element)
|
def matches_alt?(element)
|
||||||
Webrat::XML.attribute(element, "alt") =~ /^\W*#{Regexp.escape(@value.to_s)}/i
|
element["alt"] =~ /^\W*#{Regexp.escape(@value.to_s)}/i
|
||||||
end
|
end
|
||||||
|
|
||||||
def button_elements
|
def button_elements
|
||||||
Webrat::XML.xpath_search(@dom, *ButtonField.xpath_search)
|
@dom.xpath(*ButtonField.xpath_search)
|
||||||
end
|
end
|
||||||
|
|
||||||
def error_message
|
def error_message
|
||||||
|
|
|
@ -12,15 +12,15 @@ module Webrat
|
||||||
def field_element
|
def field_element
|
||||||
field_elements.detect do |field_element|
|
field_elements.detect do |field_element|
|
||||||
if @value.is_a?(Regexp)
|
if @value.is_a?(Regexp)
|
||||||
Webrat::XML.attribute(field_element, "id") =~ @value
|
field_element["id"] =~ @value
|
||||||
else
|
else
|
||||||
Webrat::XML.attribute(field_element, "id") == @value.to_s
|
field_element["id"] == @value.to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def field_elements
|
def field_elements
|
||||||
Webrat::XML.xpath_search(@dom, *Field.xpath_search)
|
@dom.xpath(*Field.xpath_search)
|
||||||
end
|
end
|
||||||
|
|
||||||
def error_message
|
def error_message
|
||||||
|
|
|
@ -20,12 +20,12 @@ module Webrat
|
||||||
|
|
||||||
def matching_label_elements
|
def matching_label_elements
|
||||||
label_elements.select do |label_element|
|
label_elements.select do |label_element|
|
||||||
text(label_element) =~ /^\W*#{Regexp.escape(@value.to_s)}\b/i
|
text(label_element) =~ /^\W*#{Regexp.escape(@value.to_s)}(\b|\Z)/i
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def label_elements
|
def label_elements
|
||||||
Webrat::XML.xpath_search(@dom, Label.xpath_search)
|
@dom.xpath(*Label.xpath_search)
|
||||||
end
|
end
|
||||||
|
|
||||||
def error_message
|
def error_message
|
||||||
|
@ -33,7 +33,7 @@ module Webrat
|
||||||
end
|
end
|
||||||
|
|
||||||
def text(element)
|
def text(element)
|
||||||
str = Webrat::XML.all_inner_text(element)
|
str = element.inner_text
|
||||||
str.gsub!("\n","")
|
str.gsub!("\n","")
|
||||||
str.strip!
|
str.strip!
|
||||||
str.squeeze!(" ")
|
str.squeeze!(" ")
|
||||||
|
|
|
@ -11,19 +11,19 @@ module Webrat
|
||||||
|
|
||||||
def field_element
|
def field_element
|
||||||
field_elements.detect do |field_element|
|
field_elements.detect do |field_element|
|
||||||
Webrat::XML.attribute(field_element, "name") == @value.to_s
|
field_element["name"] == @value.to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def field_elements
|
def field_elements
|
||||||
Webrat::XML.xpath_search(@dom, *xpath_searches)
|
@dom.xpath(*xpath_searches)
|
||||||
end
|
end
|
||||||
|
|
||||||
def xpath_searches
|
def xpath_searches
|
||||||
if @field_types.any?
|
if @field_types.any?
|
||||||
@field_types.map { |field_type| field_type.xpath_search }.flatten
|
@field_types.map { |field_type| field_type.xpath_search }.flatten
|
||||||
else
|
else
|
||||||
Array(Field.xpath_search)
|
Field.xpath_search
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ module Webrat
|
||||||
end
|
end
|
||||||
|
|
||||||
def form_element
|
def form_element
|
||||||
Webrat::XML.css_at(@dom, "#" + @value)
|
@dom.css("#" + @value).first || @dom.css(@value).first
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,16 +12,16 @@ module Webrat
|
||||||
|
|
||||||
def label_element
|
def label_element
|
||||||
label_elements.detect do |label_element|
|
label_elements.detect do |label_element|
|
||||||
text(label_element) =~ /^\W*#{Regexp.escape(@value.to_s)}\b/i
|
text(label_element) =~ /^\W*#{Regexp.escape(@value.to_s)}(\b|\Z)/i
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def label_elements
|
def label_elements
|
||||||
Webrat::XML.xpath_search(@dom, Label.xpath_search)
|
@dom.xpath(*Label.xpath_search)
|
||||||
end
|
end
|
||||||
|
|
||||||
def text(label_element)
|
def text(label_element)
|
||||||
str = Webrat::XML.all_inner_text(label_element)
|
str = label_element.inner_text
|
||||||
str.gsub!("\n","")
|
str.gsub!("\n","")
|
||||||
str.strip!
|
str.strip!
|
||||||
str.squeeze!(" ")
|
str.squeeze!(" ")
|
||||||
|
|
|
@ -10,7 +10,7 @@ module Webrat
|
||||||
end
|
end
|
||||||
|
|
||||||
def link_element
|
def link_element
|
||||||
matching_links.min { |a, b| Webrat::XML.all_inner_text(a).length <=> Webrat::XML.all_inner_text(b).length }
|
matching_links.min { |a, b| a.inner_text.length <=> b.inner_text.length }
|
||||||
end
|
end
|
||||||
|
|
||||||
def matching_links
|
def matching_links
|
||||||
|
@ -27,25 +27,33 @@ module Webrat
|
||||||
matcher = /#{Regexp.escape(@value.to_s)}/i
|
matcher = /#{Regexp.escape(@value.to_s)}/i
|
||||||
end
|
end
|
||||||
|
|
||||||
replace_nbsp(Webrat::XML.all_inner_text(link)) =~ matcher ||
|
replace_nbsp(link.inner_text) =~ matcher ||
|
||||||
replace_nbsp_ref(Webrat::XML.inner_html(link)) =~ matcher ||
|
replace_nbsp_ref(link.inner_html) =~ matcher ||
|
||||||
Webrat::XML.attribute(link, "title")=~ matcher
|
link["title"] =~ matcher
|
||||||
end
|
end
|
||||||
|
|
||||||
def matches_id?(link)
|
def matches_id?(link)
|
||||||
if @value.is_a?(Regexp)
|
if @value.is_a?(Regexp)
|
||||||
(Webrat::XML.attribute(link, "id") =~ @value) ? true : false
|
link["id"] =~ @value ? true : false
|
||||||
else
|
else
|
||||||
(Webrat::XML.attribute(link, "id") == @value) ? true : false
|
link["id"] == @value ? true : false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def link_elements
|
def link_elements
|
||||||
Webrat::XML.xpath_search(@dom, *Link.xpath_search)
|
@dom.xpath(*Link.xpath_search)
|
||||||
end
|
end
|
||||||
|
|
||||||
def replace_nbsp(str)
|
def replace_nbsp(str)
|
||||||
str.gsub([0xA0].pack('U'), ' ')
|
if str.respond_to?(:valid_encoding?)
|
||||||
|
if str.valid_encoding?
|
||||||
|
str.gsub(/\xc2\xa0/u, ' ')
|
||||||
|
else
|
||||||
|
str.force_encoding('UTF-8').gsub(/\xc2\xa0/u, ' ')
|
||||||
|
end
|
||||||
|
else
|
||||||
|
str.gsub(/\xc2\xa0/u, ' ')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def replace_nbsp_ref(str)
|
def replace_nbsp_ref(str)
|
||||||
|
|
|
@ -19,17 +19,17 @@ module Webrat
|
||||||
|
|
||||||
field.options.detect do |o|
|
field.options.detect do |o|
|
||||||
if @option_text.is_a?(Regexp)
|
if @option_text.is_a?(Regexp)
|
||||||
Webrat::XML.inner_html(o.element) =~ @option_text
|
o.element.inner_text =~ @option_text
|
||||||
else
|
else
|
||||||
Webrat::XML.inner_html(o.element) == @option_text.to_s
|
o.inner_text == @option_text.to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
option_element = option_elements.detect do |o|
|
option_element = option_elements.detect do |o|
|
||||||
if @option_text.is_a?(Regexp)
|
if @option_text.is_a?(Regexp)
|
||||||
Webrat::XML.inner_html(o) =~ @option_text
|
o.inner_text =~ @option_text
|
||||||
else
|
else
|
||||||
Webrat::XML.inner_html(o) == @option_text.to_s
|
o.inner_text == @option_text.to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ module Webrat
|
||||||
end
|
end
|
||||||
|
|
||||||
def option_elements
|
def option_elements
|
||||||
Webrat::XML.xpath_search(@dom, *SelectOption.xpath_search)
|
@dom.xpath(*SelectOption.xpath_search)
|
||||||
end
|
end
|
||||||
|
|
||||||
def error_message
|
def error_message
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
require "logger"
|
||||||
|
|
||||||
module Webrat
|
module Webrat
|
||||||
module Logging #:nodoc:
|
module Logging #:nodoc:
|
||||||
|
|
||||||
|
@ -11,9 +13,9 @@ module Webrat
|
||||||
when :rails
|
when :rails
|
||||||
defined?(RAILS_DEFAULT_LOGGER) ? RAILS_DEFAULT_LOGGER : nil
|
defined?(RAILS_DEFAULT_LOGGER) ? RAILS_DEFAULT_LOGGER : nil
|
||||||
when :merb
|
when :merb
|
||||||
Merb.logger
|
::Merb.logger
|
||||||
else
|
else
|
||||||
nil
|
@logger ||= ::Logger.new("webrat.log")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,17 +7,12 @@ module Webrat
|
||||||
end
|
end
|
||||||
|
|
||||||
def matches?(stringlike)
|
def matches?(stringlike)
|
||||||
if Webrat.configuration.parse_with_nokogiri?
|
@document = Webrat::XML.document(stringlike)
|
||||||
@document = Webrat.nokogiri_document(stringlike)
|
@element = @document.inner_text
|
||||||
else
|
|
||||||
@document = Webrat.hpricot_document(stringlike)
|
|
||||||
end
|
|
||||||
|
|
||||||
@element = Webrat::XML.inner_text(@document)
|
|
||||||
|
|
||||||
case @content
|
case @content
|
||||||
when String
|
when String
|
||||||
@element.include?(@content)
|
@element.gsub(/\s+/, ' ').include?(@content)
|
||||||
when Regexp
|
when Regexp
|
||||||
@element.match(@content)
|
@element.match(@content)
|
||||||
end
|
end
|
||||||
|
@ -26,13 +21,17 @@ module Webrat
|
||||||
# ==== Returns
|
# ==== Returns
|
||||||
# String:: The failure message.
|
# String:: The failure message.
|
||||||
def failure_message
|
def failure_message
|
||||||
"expected the following element's content to #{content_message}:\n#{@element}"
|
"expected the following element's content to #{content_message}:\n#{squeeze_space(@element)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# ==== Returns
|
# ==== Returns
|
||||||
# String:: The failure message to be displayed in negative matches.
|
# String:: The failure message to be displayed in negative matches.
|
||||||
def negative_failure_message
|
def negative_failure_message
|
||||||
"expected the following element's content to not #{content_message}:\n#{@element}"
|
"expected the following element's content to not #{content_message}:\n#{squeeze_space(@element)}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def squeeze_space(inner_text)
|
||||||
|
inner_text.gsub(/^\s*$/, "").squeeze("\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
def content_message
|
def content_message
|
||||||
|
|
|
@ -1,22 +1,44 @@
|
||||||
|
require "webrat/core/matchers/have_xpath"
|
||||||
|
|
||||||
module Webrat
|
module Webrat
|
||||||
module Matchers
|
module Matchers
|
||||||
|
|
||||||
class HaveSelector < HaveXpath #:nodoc:
|
class HaveSelector < HaveXpath #:nodoc:
|
||||||
|
|
||||||
# ==== Returns
|
# ==== Returns
|
||||||
# String:: The failure message.
|
# String:: The failure message.
|
||||||
def failure_message
|
def failure_message
|
||||||
"expected following text to match selector #{@expected}:\n#{@document}"
|
"expected following output to contain a #{tag_inspect} tag:\n#{@document}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# ==== Returns
|
# ==== Returns
|
||||||
# String:: The failure message to be displayed in negative matches.
|
# String:: The failure message to be displayed in negative matches.
|
||||||
def negative_failure_message
|
def negative_failure_message
|
||||||
"expected following text to not match selector #{@expected}:\n#{@document}"
|
"expected following output to omit a #{tag_inspect}:\n#{@document}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def tag_inspect
|
||||||
|
options = @options.dup
|
||||||
|
count = options.delete(:count)
|
||||||
|
content = options.delete(:content)
|
||||||
|
|
||||||
|
html = "<#{@expected}"
|
||||||
|
options.each do |k,v|
|
||||||
|
html << " #{k}='#{v}'"
|
||||||
|
end
|
||||||
|
|
||||||
|
if content
|
||||||
|
html << ">#{content}</#{@expected}>"
|
||||||
|
else
|
||||||
|
html << "/>"
|
||||||
|
end
|
||||||
|
|
||||||
|
html
|
||||||
end
|
end
|
||||||
|
|
||||||
def query
|
def query
|
||||||
Nokogiri::CSS::Parser.parse(*super).map { |ast| ast.to_xpath }
|
Nokogiri::CSS.parse(@expected.to_s).map do |ast|
|
||||||
|
ast.to_xpath
|
||||||
|
end.first
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -28,24 +50,24 @@ module Webrat
|
||||||
#
|
#
|
||||||
# ==== Returns
|
# ==== Returns
|
||||||
# HaveSelector:: A new have selector matcher.
|
# HaveSelector:: A new have selector matcher.
|
||||||
def have_selector(expected, &block)
|
def have_selector(name, attributes = {}, &block)
|
||||||
HaveSelector.new(expected, &block)
|
HaveSelector.new(name, attributes, &block)
|
||||||
end
|
end
|
||||||
alias_method :match_selector, :have_selector
|
alias_method :match_selector, :have_selector
|
||||||
|
|
||||||
|
|
||||||
# Asserts that the body of the response contains
|
# Asserts that the body of the response contains
|
||||||
# the supplied selector
|
# the supplied selector
|
||||||
def assert_have_selector(expected)
|
def assert_have_selector(name, attributes = {}, &block)
|
||||||
hs = HaveSelector.new(expected)
|
matcher = HaveSelector.new(name, attributes, &block)
|
||||||
assert hs.matches?(response_body), hs.failure_message
|
assert matcher.matches?(response_body), matcher.failure_message
|
||||||
end
|
end
|
||||||
|
|
||||||
# Asserts that the body of the response
|
# Asserts that the body of the response
|
||||||
# does not contain the supplied string or regepx
|
# does not contain the supplied string or regepx
|
||||||
def assert_have_no_selector(expected)
|
def assert_have_no_selector(name, attributes = {}, &block)
|
||||||
hs = HaveSelector.new(expected)
|
matcher = HaveSelector.new(name, attributes, &block)
|
||||||
assert !hs.matches?(response_body), hs.negative_failure_message
|
assert !matcher.matches?(response_body), matcher.negative_failure_message
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,70 +1,20 @@
|
||||||
module Webrat
|
require "webrat/core/matchers/have_selector"
|
||||||
|
|
||||||
|
module Webrat
|
||||||
module HaveTagMatcher
|
module HaveTagMatcher
|
||||||
|
|
||||||
class HaveTag < ::Webrat::Matchers::HaveSelector #:nodoc:
|
def have_tag(*args, &block)
|
||||||
# ==== Returns
|
have_selector(*args, &block)
|
||||||
# String:: The failure message.
|
|
||||||
def failure_message
|
|
||||||
"expected following output to contain a #{tag_inspect} tag:\n#{@document}"
|
|
||||||
end
|
|
||||||
|
|
||||||
# ==== Returns
|
|
||||||
# String:: The failure message to be displayed in negative matches.
|
|
||||||
def negative_failure_message
|
|
||||||
"expected following output to omit a #{tag_inspect}:\n#{@document}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def tag_inspect
|
|
||||||
options = @expected.last.dup
|
|
||||||
content = options.delete(:content)
|
|
||||||
|
|
||||||
html = "<#{@expected.first}"
|
|
||||||
options.each do |k,v|
|
|
||||||
html << " #{k}='#{v}'"
|
|
||||||
end
|
|
||||||
|
|
||||||
if content
|
|
||||||
html << ">#{content}</#{@expected.first}>"
|
|
||||||
else
|
|
||||||
html << "/>"
|
|
||||||
end
|
|
||||||
|
|
||||||
html
|
|
||||||
end
|
|
||||||
|
|
||||||
def query
|
|
||||||
options = @expected.last.dup
|
|
||||||
selector = @expected.first.to_s
|
|
||||||
|
|
||||||
selector << ":contains('#{options.delete(:content)}')" if options[:content]
|
|
||||||
|
|
||||||
options.each do |key, value|
|
|
||||||
selector << "[#{key}='#{value}']"
|
|
||||||
end
|
|
||||||
|
|
||||||
Nokogiri::CSS::Parser.parse(selector).map { |ast| ast.to_xpath }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def have_tag(name, attributes = {}, &block)
|
|
||||||
HaveTag.new([name, attributes], &block)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
alias_method :match_tag, :have_tag
|
alias_method :match_tag, :have_tag
|
||||||
|
|
||||||
# Asserts that the body of the response contains
|
def assert_have_tag(*args, &block)
|
||||||
# the supplied tag with the associated selectors
|
assert_have_selector(*args, &block)
|
||||||
def assert_have_tag(name, attributes = {})
|
|
||||||
ht = HaveTag.new([name, attributes])
|
|
||||||
assert ht.matches?(response_body), ht.failure_message
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Asserts that the body of the response
|
def assert_have_no_tag(*args, &block)
|
||||||
# does not contain the supplied string or regepx
|
assert_have_no_selector(*args, &block)
|
||||||
def assert_have_no_tag(name, attributes = {})
|
|
||||||
ht = HaveTag.new([name, attributes])
|
|
||||||
assert !ht.matches?(response_body), ht.negative_failure_message
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,57 +1,71 @@
|
||||||
require "webrat/core/xml/nokogiri"
|
require "webrat/core/xml"
|
||||||
require "webrat/core/xml/rexml"
|
|
||||||
|
|
||||||
module Webrat
|
module Webrat
|
||||||
module Matchers
|
module Matchers
|
||||||
|
|
||||||
class HaveXpath #:nodoc:
|
class HaveXpath #:nodoc:
|
||||||
def initialize(expected, &block)
|
def initialize(expected, options = {}, &block)
|
||||||
@expected = expected
|
@expected = expected
|
||||||
|
@options = options
|
||||||
@block = block
|
@block = block
|
||||||
end
|
end
|
||||||
|
|
||||||
def matches?(stringlike)
|
def matches?(stringlike, &block)
|
||||||
if Webrat.configuration.parse_with_nokogiri?
|
@block ||= block
|
||||||
matches_nokogiri?(stringlike)
|
matched = matches(stringlike)
|
||||||
|
|
||||||
|
@block.call(matched) if @block
|
||||||
|
|
||||||
|
if @options[:count]
|
||||||
|
matched.size == @options[:count].to_i
|
||||||
else
|
else
|
||||||
matches_rexml?(stringlike)
|
matched.any?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def matches_rexml?(stringlike)
|
def matches(stringlike)
|
||||||
if REXML::Node === stringlike || Array === stringlike
|
nokogiri_matches(stringlike)
|
||||||
@query = query.map { |q| q.gsub(%r'//', './') }
|
|
||||||
else
|
|
||||||
@query = query
|
|
||||||
end
|
|
||||||
|
|
||||||
@document = Webrat.rexml_document(stringlike)
|
|
||||||
|
|
||||||
matched = @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
|
|
||||||
|
|
||||||
matched.any? && (!@block || @block.call(matched))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def matches_nokogiri?(stringlike)
|
def nokogiri_matches(stringlike)
|
||||||
if Nokogiri::XML::NodeSet === stringlike
|
if Nokogiri::XML::NodeSet === stringlike
|
||||||
@query = query.map { |q| q.gsub(%r'//', './') }
|
@query = query.gsub(%r'^//', './/')
|
||||||
else
|
else
|
||||||
@query = query
|
@query = query
|
||||||
end
|
end
|
||||||
|
|
||||||
|
add_options_conditions_to(@query)
|
||||||
|
|
||||||
@document = Webrat::XML.document(stringlike)
|
@document = Webrat::XML.document(stringlike)
|
||||||
matched = @document.xpath(*@query)
|
@document.xpath(*@query)
|
||||||
matched.any? && (!@block || @block.call(matched))
|
end
|
||||||
|
|
||||||
|
def add_options_conditions_to(query)
|
||||||
|
add_attributes_conditions_to(query)
|
||||||
|
add_content_condition_to(query)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_attributes_conditions_to(query)
|
||||||
|
attribute_conditions = []
|
||||||
|
|
||||||
|
@options.each do |key, value|
|
||||||
|
next if [:content, :count].include?(key)
|
||||||
|
attribute_conditions << "@#{key} = #{xpath_escape(value)}"
|
||||||
|
end
|
||||||
|
|
||||||
|
if attribute_conditions.any?
|
||||||
|
query << "[#{attribute_conditions.join(' and ')}]"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_content_condition_to(query)
|
||||||
|
if @options[:content]
|
||||||
|
query << "[contains(., #{xpath_escape(@options[:content])})]"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def query
|
def query
|
||||||
[@expected].flatten.compact
|
@expected
|
||||||
end
|
end
|
||||||
|
|
||||||
# ==== Returns
|
# ==== Returns
|
||||||
|
@ -65,6 +79,23 @@ module Webrat
|
||||||
def negative_failure_message
|
def negative_failure_message
|
||||||
"expected following text to not match xpath #{@expected}:\n#{@document}"
|
"expected following text to not match xpath #{@expected}:\n#{@document}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def xpath_escape(string)
|
||||||
|
if string.include?("'") && string.include?('"')
|
||||||
|
parts = string.split("'").map do |part|
|
||||||
|
"'#{part}'"
|
||||||
|
end
|
||||||
|
|
||||||
|
"concat(" + parts.join(", \"'\", ") + ")"
|
||||||
|
elsif string.include?("'")
|
||||||
|
"\"#{string}\""
|
||||||
|
else
|
||||||
|
"'#{string}'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Matches HTML content against an XPath query
|
# Matches HTML content against an XPath query
|
||||||
|
@ -74,18 +105,18 @@ module Webrat
|
||||||
#
|
#
|
||||||
# ==== Returns
|
# ==== Returns
|
||||||
# HaveXpath:: A new have xpath matcher.
|
# HaveXpath:: A new have xpath matcher.
|
||||||
def have_xpath(expected, &block)
|
def have_xpath(expected, options = {}, &block)
|
||||||
HaveXpath.new(expected, &block)
|
HaveXpath.new(expected, options, &block)
|
||||||
end
|
end
|
||||||
alias_method :match_xpath, :have_xpath
|
alias_method :match_xpath, :have_xpath
|
||||||
|
|
||||||
def assert_have_xpath(expected, &block)
|
def assert_have_xpath(expected, options = {}, &block)
|
||||||
hs = HaveXpath.new(expected, &block)
|
hs = HaveXpath.new(expected, options, &block)
|
||||||
assert hs.matches?(response_body), hs.failure_message
|
assert hs.matches?(response_body), hs.failure_message
|
||||||
end
|
end
|
||||||
|
|
||||||
def assert_have_no_xpath(expected, &block)
|
def assert_have_no_xpath(expected, options = {}, &block)
|
||||||
hs = HaveXpath.new(expected, &block)
|
hs = HaveXpath.new(expected, options, &block)
|
||||||
assert !hs.matches?(response_body), hs.negative_failure_message
|
assert !hs.matches?(response_body), hs.negative_failure_message
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ module Webrat
|
||||||
|
|
||||||
def self.delegate_to_session(*meths)
|
def self.delegate_to_session(*meths)
|
||||||
meths.each do |meth|
|
meths.each do |meth|
|
||||||
self.class_eval <<-RUBY
|
self.class_eval(<<-RUBY, __FILE__, __LINE__)
|
||||||
def #{meth}(*args, &blk)
|
def #{meth}(*args, &blk)
|
||||||
webrat_session.#{meth}(*args, &blk)
|
webrat_session.#{meth}(*args, &blk)
|
||||||
end
|
end
|
||||||
|
@ -16,7 +16,11 @@ module Webrat
|
||||||
end
|
end
|
||||||
|
|
||||||
def webrat_session
|
def webrat_session
|
||||||
@_webrat_session ||= ::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
|
end
|
||||||
|
|
||||||
# all of these methods delegate to the @session, which should
|
# all of these methods delegate to the @session, which should
|
||||||
|
@ -35,6 +39,7 @@ module Webrat
|
||||||
:unchecks, :uncheck,
|
:unchecks, :uncheck,
|
||||||
:chooses, :choose,
|
:chooses, :choose,
|
||||||
:selects, :select,
|
:selects, :select,
|
||||||
|
:unselects, :unselect,
|
||||||
:attaches_file, :attach_file,
|
:attaches_file, :attach_file,
|
||||||
:current_page,
|
:current_page,
|
||||||
:current_url,
|
:current_url,
|
||||||
|
@ -53,9 +58,7 @@ module Webrat
|
||||||
:field_by_xpath,
|
:field_by_xpath,
|
||||||
:field_with_id,
|
:field_with_id,
|
||||||
:selenium,
|
:selenium,
|
||||||
:simulate, :automate
|
:simulate, :automate,
|
||||||
|
:field_named
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -1,29 +1,18 @@
|
||||||
module Webrat #:nodoc:
|
module Webrat #:nodoc:
|
||||||
module MIME #: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:
|
def mime_type(type)
|
||||||
if string_or_symbol.is_a?(String)
|
return type if type.nil? || type.to_s.include?("/")
|
||||||
string_or_symbol
|
type = ".#{type}" unless type.to_s[0] == ?.
|
||||||
else
|
MIME_TYPES.fetch(type) { |invalid_type|
|
||||||
case string_or_symbol
|
raise ArgumentError.new("Invalid Mime type: #{invalid_type}")
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module_function :mime_type
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -6,44 +6,22 @@ module Webrat
|
||||||
# Example:
|
# Example:
|
||||||
# save_and_open_page
|
# save_and_open_page
|
||||||
def save_and_open_page
|
def save_and_open_page
|
||||||
return unless File.exist?(saved_page_dir)
|
return unless File.exist?(Webrat.configuration.saved_pages_dir)
|
||||||
|
|
||||||
filename = "#{saved_page_dir}/webrat-#{Time.now.to_i}.html"
|
filename = "#{Webrat.configuration.saved_pages_dir}/webrat-#{Time.now.to_i}.html"
|
||||||
|
|
||||||
File.open(filename, "w") do |f|
|
File.open(filename, "w") do |f|
|
||||||
f.write rewrite_css_and_image_references(response_body)
|
f.write response_body
|
||||||
end
|
end
|
||||||
|
|
||||||
open_in_browser(filename)
|
open_in_browser(filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
def open_in_browser(path) # :nodoc
|
def open_in_browser(path) # :nodoc
|
||||||
platform = ruby_platform
|
require "launchy"
|
||||||
if platform =~ /cygwin/ || platform =~ /win32/
|
Launchy::Browser.run(path)
|
||||||
`rundll32 url.dll,FileProtocolHandler #{path.gsub("/", "\\\\")}`
|
rescue LoadError
|
||||||
elsif platform =~ /darwin/
|
warn "Sorry, you need to install launchy to open pages: `gem install launchy`"
|
||||||
`open #{path}`
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def rewrite_css_and_image_references(response_html) # :nodoc:
|
|
||||||
return response_html unless doc_root
|
|
||||||
response_html.gsub(/"\/(stylesheets|images)/, doc_root + '/\1')
|
|
||||||
end
|
|
||||||
|
|
||||||
def saved_page_dir #:nodoc:
|
|
||||||
File.expand_path(".")
|
|
||||||
end
|
|
||||||
|
|
||||||
def doc_root #:nodoc:
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
# accessor for testing
|
|
||||||
def ruby_platform
|
|
||||||
RUBY_PLATFORM
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,6 +28,7 @@ module Webrat
|
||||||
attr_reader :session
|
attr_reader :session
|
||||||
|
|
||||||
def initialize(session, &block) #:nodoc:
|
def initialize(session, &block) #:nodoc:
|
||||||
|
@selector, @dom = nil
|
||||||
@session = session
|
@session = session
|
||||||
instance_eval(&block) if block_given?
|
instance_eval(&block) if block_given?
|
||||||
|
|
||||||
|
@ -112,6 +113,21 @@ module Webrat
|
||||||
|
|
||||||
webrat_deprecate :selects, :select
|
webrat_deprecate :selects, :select
|
||||||
|
|
||||||
|
# Verifies that a an option element exists on the current page with the specified
|
||||||
|
# text. You can optionally restrict the search to a specific select list by
|
||||||
|
# assigning <tt>options[:from]</tt> the value of the select list's name or
|
||||||
|
# a label. Remove the option's value before the form is submitted.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# unselect "January"
|
||||||
|
# unselect "February", :from => "event_month"
|
||||||
|
# unselect "February", :from => "Event Month"
|
||||||
|
def unselect(option_text, options={})
|
||||||
|
select_option(option_text, options[:from]).unchoose
|
||||||
|
end
|
||||||
|
|
||||||
|
webrat_deprecate :unselects, :unselect
|
||||||
|
|
||||||
DATE_TIME_SUFFIXES = {
|
DATE_TIME_SUFFIXES = {
|
||||||
:year => '1i',
|
:year => '1i',
|
||||||
:month => '2i',
|
:month => '2i',
|
||||||
|
@ -209,8 +225,8 @@ module Webrat
|
||||||
# along with the form. An optional <tt>content_type</tt> may be given.
|
# along with the form. An optional <tt>content_type</tt> may be given.
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
# attaches_file "Resume", "/path/to/the/resume.txt"
|
# attach_file "Resume", "/path/to/the/resume.txt"
|
||||||
# attaches_file "Photo", "/path/to/the/image.png", "image/png"
|
# attach_file "Photo", "/path/to/the/image.png", "image/png"
|
||||||
def attach_file(field_locator, path, content_type = nil)
|
def attach_file(field_locator, path, content_type = nil)
|
||||||
locate_field(field_locator, FileField).set(path, content_type)
|
locate_field(field_locator, FileField).set(path, content_type)
|
||||||
end
|
end
|
||||||
|
@ -312,12 +328,12 @@ module Webrat
|
||||||
dom = Webrat::XML.html_document(@response_body)
|
dom = Webrat::XML.html_document(@response_body)
|
||||||
end
|
end
|
||||||
|
|
||||||
Webrat.define_dom_method(@response, dom)
|
Webrat::XML.define_dom_method(@response, dom)
|
||||||
return dom
|
return dom
|
||||||
end
|
end
|
||||||
|
|
||||||
def scoped_dom
|
def scoped_dom
|
||||||
Webrat::XML.css_at(@scope.dom, @selector)
|
@scope.dom.css(@selector).first
|
||||||
end
|
end
|
||||||
|
|
||||||
def locate_field(field_locator, *field_types) #:nodoc:
|
def locate_field(field_locator, *field_types) #:nodoc:
|
||||||
|
|
|
@ -9,20 +9,34 @@ module Webrat
|
||||||
class PageLoadError < WebratError
|
class PageLoadError < WebratError
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class InfiniteRedirectError < WebratError
|
||||||
|
end
|
||||||
|
|
||||||
def self.session_class
|
def self.session_class
|
||||||
|
if Webrat.configuration.mode == :selenium
|
||||||
|
SeleniumSession
|
||||||
|
else
|
||||||
|
Session
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.adapter_class
|
||||||
case Webrat.configuration.mode
|
case Webrat.configuration.mode
|
||||||
when :rails
|
when :rails
|
||||||
RailsSession
|
RailsAdapter
|
||||||
when :merb
|
when :merb
|
||||||
MerbSession
|
MerbAdapter
|
||||||
when :selenium
|
|
||||||
SeleniumSession
|
|
||||||
when :rack
|
when :rack
|
||||||
RackSession
|
RackAdapter
|
||||||
|
when :rack_test
|
||||||
|
warn("The :rack_test mode is deprecated. Please use :rack instead")
|
||||||
|
require "webrat/rack"
|
||||||
|
RackAdapter
|
||||||
when :sinatra
|
when :sinatra
|
||||||
SinatraSession
|
warn("The :sinatra mode is deprecated. Please use :rack instead")
|
||||||
|
SinatraAdapter
|
||||||
when :mechanize
|
when :mechanize
|
||||||
MechanizeSession
|
MechanizeAdapter
|
||||||
else
|
else
|
||||||
raise WebratError.new(<<-STR)
|
raise WebratError.new(<<-STR)
|
||||||
Unknown Webrat mode: #{Webrat.configuration.mode.inspect}
|
Unknown Webrat mode: #{Webrat.configuration.mode.inspect}
|
||||||
|
@ -45,16 +59,23 @@ For example:
|
||||||
extend Forwardable
|
extend Forwardable
|
||||||
include Logging
|
include Logging
|
||||||
include SaveAndOpenPage
|
include SaveAndOpenPage
|
||||||
|
|
||||||
|
attr_accessor :adapter
|
||||||
|
|
||||||
attr_reader :current_url
|
attr_reader :current_url
|
||||||
attr_reader :elements
|
attr_reader :elements
|
||||||
|
|
||||||
def initialize(context = nil) #:nodoc:
|
def_delegators :@adapter, :response, :response_code, :response_body, :response_headers,
|
||||||
|
:response_body=, :response_code=,
|
||||||
|
:get, :post, :put, :delete
|
||||||
|
|
||||||
|
def initialize(adapter = nil)
|
||||||
|
@adapter = adapter
|
||||||
@http_method = :get
|
@http_method = :get
|
||||||
@data = {}
|
@data = {}
|
||||||
@default_headers = {}
|
@default_headers = {}
|
||||||
@custom_headers = {}
|
@custom_headers = {}
|
||||||
@context = context
|
@current_url = nil
|
||||||
|
|
||||||
reset
|
reset
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -64,6 +85,7 @@ For example:
|
||||||
|
|
||||||
# For backwards compatibility -- removing in 1.0
|
# For backwards compatibility -- removing in 1.0
|
||||||
def current_page #:nodoc:
|
def current_page #:nodoc:
|
||||||
|
warn "current_page is deprecated and will be going away in the next release. Use current_url instead."
|
||||||
page = OpenStruct.new
|
page = OpenStruct.new
|
||||||
page.url = @current_url
|
page.url = @current_url
|
||||||
page.http_method = @http_method
|
page.http_method = @http_method
|
||||||
|
@ -71,10 +93,6 @@ For example:
|
||||||
page
|
page
|
||||||
end
|
end
|
||||||
|
|
||||||
def doc_root #:nodoc:
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def header(key, value)
|
def header(key, value)
|
||||||
@custom_headers[key] = value
|
@custom_headers[key] = value
|
||||||
end
|
end
|
||||||
|
@ -84,7 +102,7 @@ For example:
|
||||||
end
|
end
|
||||||
|
|
||||||
def basic_auth(user, pass)
|
def basic_auth(user, pass)
|
||||||
encoded_login = ["#{user}:#{pass}"].pack("m*")
|
encoded_login = ["#{user}:#{pass}"].pack("m*").gsub(/\n/, '')
|
||||||
header('HTTP_AUTHORIZATION', "Basic #{encoded_login}")
|
header('HTTP_AUTHORIZATION', "Basic #{encoded_login}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -97,11 +115,8 @@ For example:
|
||||||
h['HTTP_REFERER'] = @current_url if @current_url
|
h['HTTP_REFERER'] = @current_url if @current_url
|
||||||
|
|
||||||
debug_log "REQUESTING PAGE: #{http_method.to_s.upcase} #{url} with #{data.inspect} and HTTP headers #{h.inspect}"
|
debug_log "REQUESTING PAGE: #{http_method.to_s.upcase} #{url} with #{data.inspect} and HTTP headers #{h.inspect}"
|
||||||
if h.empty?
|
|
||||||
send "#{http_method}", url, data || {}
|
process_request(http_method, url, data, h)
|
||||||
else
|
|
||||||
send "#{http_method}", url, data || {}, h
|
|
||||||
end
|
|
||||||
|
|
||||||
save_and_open_page if exception_caught? && Webrat.configuration.open_error_files?
|
save_and_open_page if exception_caught? && Webrat.configuration.open_error_files?
|
||||||
raise PageLoadError.new("Page load was not successful (Code: #{response_code.inspect}):\n#{formatted_error}") unless success_code?
|
raise PageLoadError.new("Page load was not successful (Code: #{response_code.inspect}):\n#{formatted_error}") unless success_code?
|
||||||
|
@ -112,21 +127,49 @@ For example:
|
||||||
@http_method = http_method
|
@http_method = http_method
|
||||||
@data = data
|
@data = data
|
||||||
|
|
||||||
request_page(response_location, :get, data) if internal_redirect?
|
if internal_redirect?
|
||||||
|
check_for_infinite_redirects
|
||||||
|
request_page(response_location, :get, {})
|
||||||
|
end
|
||||||
|
|
||||||
return response
|
return response
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_for_infinite_redirects
|
||||||
|
if current_url == response_location
|
||||||
|
@_identical_redirect_count ||= 0
|
||||||
|
@_identical_redirect_count += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if infinite_redirect_limit_exceeded?
|
||||||
|
raise InfiniteRedirectError.new("#{Webrat.configuration.infinite_redirect_limit} redirects to the same URL (#{current_url.inspect})")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def infinite_redirect_limit_exceeded?
|
||||||
|
Webrat.configuration.infinite_redirect_limit &&
|
||||||
|
(@_identical_redirect_count || 0) > Webrat.configuration.infinite_redirect_limit
|
||||||
|
end
|
||||||
|
|
||||||
def success_code? #:nodoc:
|
def success_code? #:nodoc:
|
||||||
(200..499).include?(response_code)
|
(200..499).include?(response_code)
|
||||||
end
|
end
|
||||||
|
|
||||||
def redirect? #:nodoc:
|
def redirect? #:nodoc:
|
||||||
response_code / 100 == 3
|
[301, 302, 303, 307].include?(response_code)
|
||||||
end
|
end
|
||||||
|
|
||||||
def internal_redirect? #:nodoc:
|
def internal_redirect?
|
||||||
redirect? && current_host == response_location_host
|
return false unless redirect?
|
||||||
|
#should keep internal_redirects if the subdomain changes
|
||||||
|
current_host_domain = current_host.split('.')[-2..-1].join('.') rescue current_host
|
||||||
|
response_location_host_domain = response_location_host.split('.')[-2..-1].join('.') rescue response_location_host
|
||||||
|
current_host_domain == response_location_host_domain
|
||||||
|
end
|
||||||
|
|
||||||
|
#easy helper to pull out where we were redirected to
|
||||||
|
def redirected_to
|
||||||
|
redirect? ? response_location : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def exception_caught? #:nodoc:
|
def exception_caught? #:nodoc:
|
||||||
|
@ -214,6 +257,7 @@ For example:
|
||||||
def_delegators :current_scope, :uncheck, :unchecks
|
def_delegators :current_scope, :uncheck, :unchecks
|
||||||
def_delegators :current_scope, :choose, :chooses
|
def_delegators :current_scope, :choose, :chooses
|
||||||
def_delegators :current_scope, :select, :selects
|
def_delegators :current_scope, :select, :selects
|
||||||
|
def_delegators :current_scope, :unselect, :unselects
|
||||||
def_delegators :current_scope, :select_datetime, :selects_datetime
|
def_delegators :current_scope, :select_datetime, :selects_datetime
|
||||||
def_delegators :current_scope, :select_date, :selects_date
|
def_delegators :current_scope, :select_date, :selects_date
|
||||||
def_delegators :current_scope, :select_time, :selects_time
|
def_delegators :current_scope, :select_time, :selects_time
|
||||||
|
@ -225,15 +269,24 @@ For example:
|
||||||
def_delegators :current_scope, :field_by_xpath
|
def_delegators :current_scope, :field_by_xpath
|
||||||
def_delegators :current_scope, :field_with_id
|
def_delegators :current_scope, :field_with_id
|
||||||
def_delegators :current_scope, :select_option
|
def_delegators :current_scope, :select_option
|
||||||
|
def_delegators :current_scope, :field_named
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def process_request(http_method, url, data, headers)
|
||||||
|
if headers.empty?
|
||||||
|
send "#{http_method}", url, data || {}
|
||||||
|
else
|
||||||
|
send "#{http_method}", url, data || {}, headers
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def response_location
|
def response_location
|
||||||
response.headers["Location"]
|
response_headers['Location']
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_host
|
def current_host
|
||||||
URI.parse(current_url).host || "www.example.com"
|
URI.parse(current_url).host || @custom_headers["Host"] || "www.example.com"
|
||||||
end
|
end
|
||||||
|
|
||||||
def response_location_host
|
def response_location_host
|
||||||
|
|
|
@ -1,115 +1,72 @@
|
||||||
require "webrat/core/xml/nokogiri"
|
require "webrat/core_extensions/meta_class"
|
||||||
require "webrat/core/xml/hpricot"
|
|
||||||
require "webrat/core/xml/rexml"
|
|
||||||
|
|
||||||
module Webrat #:nodoc:
|
module Webrat #:nodoc:
|
||||||
module XML #:nodoc:
|
module XML #:nodoc:
|
||||||
|
|
||||||
def self.document(stringlike) #:nodoc:
|
def self.document(stringlike) #:nodoc:
|
||||||
if Webrat.configuration.parse_with_nokogiri?
|
return stringlike.dom if stringlike.respond_to?(:dom)
|
||||||
Webrat.nokogiri_document(stringlike)
|
|
||||||
|
if Nokogiri::HTML::Document === stringlike
|
||||||
|
stringlike
|
||||||
|
elsif Nokogiri::XML::NodeSet === stringlike
|
||||||
|
stringlike
|
||||||
|
elsif stringlike.respond_to?(:body)
|
||||||
|
Nokogiri::HTML(stringlike.body.to_s)
|
||||||
else
|
else
|
||||||
Webrat.rexml_document(Webrat.hpricot_document(stringlike).to_html)
|
Nokogiri::HTML(stringlike.to_s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.html_document(stringlike) #:nodoc:
|
def self.html_document(stringlike) #:nodoc:
|
||||||
if Webrat.configuration.parse_with_nokogiri?
|
return stringlike.dom if stringlike.respond_to?(:dom)
|
||||||
Webrat.html_nokogiri_document(stringlike)
|
|
||||||
|
if Nokogiri::HTML::Document === stringlike
|
||||||
|
stringlike
|
||||||
|
elsif Nokogiri::XML::NodeSet === stringlike
|
||||||
|
stringlike
|
||||||
|
elsif stringlike.respond_to?(:body)
|
||||||
|
Nokogiri::HTML(stringlike.body.to_s)
|
||||||
else
|
else
|
||||||
Webrat.rexml_document(Webrat.hpricot_document(stringlike).to_html)
|
Nokogiri::HTML(stringlike.to_s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.xml_document(stringlike) #:nodoc:
|
def self.xml_document(stringlike) #:nodoc:
|
||||||
if Webrat.configuration.parse_with_nokogiri?
|
return stringlike.dom if stringlike.respond_to?(:dom)
|
||||||
Webrat.xml_nokogiri_document(stringlike)
|
|
||||||
|
if Nokogiri::HTML::Document === stringlike
|
||||||
|
stringlike
|
||||||
|
elsif Nokogiri::XML::NodeSet === stringlike
|
||||||
|
stringlike
|
||||||
|
elsif stringlike.respond_to?(:body)
|
||||||
|
Nokogiri::XML(stringlike.body.to_s)
|
||||||
else
|
else
|
||||||
Webrat.rexml_document(Webrat.hpricot_document(stringlike).to_html)
|
Nokogiri::XML(stringlike.to_s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.to_html(element)
|
def self.define_dom_method(object, dom) #:nodoc:
|
||||||
if Webrat.configuration.parse_with_nokogiri?
|
object.meta_class.send(:define_method, :dom) do
|
||||||
element.to_html
|
dom
|
||||||
else
|
|
||||||
element.to_s
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.inner_html(element)
|
|
||||||
if Webrat.configuration.parse_with_nokogiri?
|
|
||||||
element.inner_html
|
|
||||||
else
|
|
||||||
element.text
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.all_inner_text(element)
|
|
||||||
if Webrat.configuration.parse_with_nokogiri?
|
|
||||||
element.inner_text
|
|
||||||
else
|
|
||||||
Hpricot(element.to_s).children.first.inner_text
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.inner_text(element)
|
|
||||||
if Webrat.configuration.parse_with_nokogiri?
|
|
||||||
element.inner_text
|
|
||||||
else
|
|
||||||
if defined?(Hpricot::Doc) && element.is_a?(Hpricot::Doc)
|
|
||||||
element.inner_text
|
|
||||||
else
|
|
||||||
element.text
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.xpath_to(element)
|
|
||||||
if Webrat.configuration.parse_with_nokogiri?
|
|
||||||
element.path
|
|
||||||
else
|
|
||||||
element.xpath
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.attribute(element, attribute_name)
|
|
||||||
return element[attribute_name] if element.is_a?(Hash)
|
|
||||||
|
|
||||||
if Webrat.configuration.parse_with_nokogiri?
|
|
||||||
element[attribute_name]
|
|
||||||
else
|
|
||||||
element.attributes[attribute_name]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.xpath_at(*args)
|
|
||||||
xpath_search(*args).first
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.css_at(*args)
|
|
||||||
css_search(*args).first
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.xpath_search(element, *searches)
|
|
||||||
searches.flatten.map do |search|
|
|
||||||
if Webrat.configuration.parse_with_nokogiri?
|
|
||||||
element.xpath(search)
|
|
||||||
else
|
|
||||||
REXML::XPath.match(element, search)
|
|
||||||
end
|
|
||||||
end.flatten.compact
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.css_search(element, *searches) #:nodoc:
|
|
||||||
xpath_search(element, css_to_xpath(*searches))
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.css_to_xpath(*selectors)
|
|
||||||
selectors.map do |rule|
|
|
||||||
Nokogiri::CSS.xpath_for(rule, :prefix => ".//")
|
|
||||||
end.flatten.uniq
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module Nokogiri #:nodoc:
|
||||||
|
module CSS #:nodoc:
|
||||||
|
class XPathVisitor #:nodoc:
|
||||||
|
|
||||||
|
def visit_pseudo_class_text(node) #:nodoc:
|
||||||
|
"@type='text'"
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit_pseudo_class_password(node) #:nodoc:
|
||||||
|
"@type='password'"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -1,131 +0,0 @@
|
||||||
# This class has dubious semantics and we only have it so that
|
|
||||||
# people can write params[:key] instead of params['key']
|
|
||||||
# and they get the same value for both keys.
|
|
||||||
class HashWithIndifferentAccess < Hash #:nodoc:
|
|
||||||
def initialize(constructor = {})
|
|
||||||
if constructor.is_a?(Hash)
|
|
||||||
super()
|
|
||||||
update(constructor)
|
|
||||||
else
|
|
||||||
super(constructor)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def default(key = nil)
|
|
||||||
if key.is_a?(Symbol) && include?(key = key.to_s)
|
|
||||||
self[key]
|
|
||||||
else
|
|
||||||
super
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
|
|
||||||
alias_method :regular_update, :update unless method_defined?(:regular_update)
|
|
||||||
|
|
||||||
#
|
|
||||||
# Assigns a new value to the hash.
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
#
|
|
||||||
# hash = HashWithIndifferentAccess.new
|
|
||||||
# hash[:key] = "value"
|
|
||||||
#
|
|
||||||
def []=(key, value)
|
|
||||||
regular_writer(convert_key(key), convert_value(value))
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
|
||||||
# Updates the instantized hash with values from the second.
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
#
|
|
||||||
# >> hash_1 = HashWithIndifferentAccess.new
|
|
||||||
# => {}
|
|
||||||
#
|
|
||||||
# >> hash_1[:key] = "value"
|
|
||||||
# => "value"
|
|
||||||
#
|
|
||||||
# >> hash_2 = HashWithIndifferentAccess.new
|
|
||||||
# => {}
|
|
||||||
#
|
|
||||||
# >> hash_2[:key] = "New Value!"
|
|
||||||
# => "New Value!"
|
|
||||||
#
|
|
||||||
# >> hash_1.update(hash_2)
|
|
||||||
# => {"key"=>"New Value!"}
|
|
||||||
#
|
|
||||||
def update(other_hash)
|
|
||||||
other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
alias_method :merge!, :update
|
|
||||||
|
|
||||||
# Checks the hash for a key matching the argument passed in
|
|
||||||
def key?(key)
|
|
||||||
super(convert_key(key))
|
|
||||||
end
|
|
||||||
|
|
||||||
alias_method :include?, :key?
|
|
||||||
alias_method :has_key?, :key?
|
|
||||||
alias_method :member?, :key?
|
|
||||||
|
|
||||||
# Fetches the value for the specified key, same as doing hash[key]
|
|
||||||
def fetch(key, *extras)
|
|
||||||
super(convert_key(key), *extras)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns an array of the values at the specified indicies.
|
|
||||||
def values_at(*indices)
|
|
||||||
indices.collect {|key| self[convert_key(key)]}
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns an exact copy of the hash.
|
|
||||||
def dup
|
|
||||||
HashWithIndifferentAccess.new(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Merges the instantized and the specified hashes together, giving precedence to the values from the second hash
|
|
||||||
# Does not overwrite the existing hash.
|
|
||||||
def merge(hash)
|
|
||||||
self.dup.update(hash)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Removes a specified key from the hash.
|
|
||||||
def delete(key)
|
|
||||||
super(convert_key(key))
|
|
||||||
end
|
|
||||||
|
|
||||||
def stringify_keys!; self end
|
|
||||||
def symbolize_keys!; self end
|
|
||||||
def to_options!; self end
|
|
||||||
|
|
||||||
# Convert to a Hash with String keys.
|
|
||||||
def to_hash
|
|
||||||
Hash.new(default).merge(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
|
||||||
def convert_key(key)
|
|
||||||
key.kind_of?(Symbol) ? key.to_s : key
|
|
||||||
end
|
|
||||||
|
|
||||||
def convert_value(value)
|
|
||||||
case value
|
|
||||||
when Hash
|
|
||||||
value.with_indifferent_access
|
|
||||||
when Array
|
|
||||||
value.collect { |e| e.is_a?(Hash) ? e.with_indifferent_access : e }
|
|
||||||
else
|
|
||||||
value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class Hash #:nodoc:
|
|
||||||
def with_indifferent_access
|
|
||||||
hash = HashWithIndifferentAccess.new(self)
|
|
||||||
hash.default = self.default
|
|
||||||
hash
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,5 +1,5 @@
|
||||||
class NilClass #:nodoc:
|
class NilClass #:nodoc:
|
||||||
def to_param
|
def to_query_string
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -0,0 +1,27 @@
|
||||||
|
class TCPSocket
|
||||||
|
|
||||||
|
def self.wait_for_service_with_timeout(options)
|
||||||
|
start_time = Time.now
|
||||||
|
|
||||||
|
until listening_service?(options)
|
||||||
|
verbose_wait
|
||||||
|
|
||||||
|
if options[:timeout] && (Time.now > start_time + options[:timeout])
|
||||||
|
raise SocketError.new("Socket did not open within #{options[:timeout]} seconds")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.wait_for_service_termination_with_timeout(options)
|
||||||
|
start_time = Time.now
|
||||||
|
|
||||||
|
while listening_service?(options)
|
||||||
|
verbose_wait
|
||||||
|
|
||||||
|
if options[:timeout] && (Time.now > start_time + options[:timeout])
|
||||||
|
raise SocketError.new("Socket did not terminate within #{options[:timeout]} seconds")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -1,65 +0,0 @@
|
||||||
require "webrat"
|
|
||||||
|
|
||||||
require "cgi"
|
|
||||||
gem "extlib"
|
|
||||||
require "extlib"
|
|
||||||
require "merb-core"
|
|
||||||
|
|
||||||
HashWithIndifferentAccess = Mash
|
|
||||||
|
|
||||||
module Webrat
|
|
||||||
class MerbSession < Session #:nodoc:
|
|
||||||
include Merb::Test::MakeRequest
|
|
||||||
|
|
||||||
attr_accessor :response
|
|
||||||
|
|
||||||
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)
|
|
||||||
@response = request(url,
|
|
||||||
:params => (data && data.any?) ? data : nil,
|
|
||||||
:headers => headers,
|
|
||||||
:method => method)
|
|
||||||
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
|
|
||||||
|
|
||||||
class Merb::Test::RspecStory #:nodoc:
|
|
||||||
def browser
|
|
||||||
@browser ||= Webrat::MerbSession.new
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,24 +0,0 @@
|
||||||
require 'webrat'
|
|
||||||
|
|
||||||
class CGIMethods #:nodoc:
|
|
||||||
def self.parse_query_parameters(params)
|
|
||||||
hash = {}
|
|
||||||
params.split('&').each do |p|
|
|
||||||
pair = p.split('=')
|
|
||||||
hash[pair[0]] = pair[1]
|
|
||||||
end
|
|
||||||
hash
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
module Webrat
|
|
||||||
class RackSession < Session #:nodoc:
|
|
||||||
def response_body
|
|
||||||
@response.body
|
|
||||||
end
|
|
||||||
|
|
||||||
def response_code
|
|
||||||
@response.status
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,13 +1,2 @@
|
||||||
# Supports using the matchers in controller, helper, and view specs if you're
|
warn("Requiring 'webrat/rspec-rails' is deprecated. Please require 'webrat/integrations/rspec-rails' instead")
|
||||||
# using rspec-rails. Just add a require statement to spec/spec_helper.rb or env.rb:
|
require "webrat/integrations/rspec-rails"
|
||||||
#
|
|
||||||
# require 'webrat/rspec-rails'
|
|
||||||
#
|
|
||||||
require "webrat/core/matchers"
|
|
||||||
|
|
||||||
Spec::Runner.configure do |config|
|
|
||||||
# rspec should support :type => [:controller, :helper, :view] - but until it does ...
|
|
||||||
config.include(Webrat::Matchers, :type => :controller)
|
|
||||||
config.include(Webrat::Matchers, :type => :helper)
|
|
||||||
config.include(Webrat::Matchers, :type => :view)
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,41 +1,11 @@
|
||||||
require "webrat"
|
require "webrat"
|
||||||
gem "selenium-client", ">=1.2.9"
|
|
||||||
require "selenium/client"
|
require "selenium/client"
|
||||||
|
require "webrat/selenium/silence_stream"
|
||||||
require "webrat/selenium/selenium_session"
|
require "webrat/selenium/selenium_session"
|
||||||
require "webrat/selenium/matchers"
|
require "webrat/selenium/matchers"
|
||||||
|
require "webrat/core_extensions/tcp_socket"
|
||||||
|
|
||||||
module Webrat
|
module Webrat
|
||||||
|
|
||||||
def self.with_selenium_server #:nodoc:
|
|
||||||
start_selenium_server
|
|
||||||
yield
|
|
||||||
stop_selenium_server
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.start_selenium_server #:nodoc:
|
|
||||||
unless Webrat.configuration.selenium_server_address
|
|
||||||
remote_control = ::Selenium::RemoteControl::RemoteControl.new("0.0.0.0", Webrat.configuration.selenium_server_port, 5)
|
|
||||||
remote_control.jar_file = File.expand_path(__FILE__ + "../../../../vendor/selenium-server.jar")
|
|
||||||
remote_control.start :background => true
|
|
||||||
end
|
|
||||||
TCPSocket.wait_for_service :host => (Webrat.configuration.selenium_server_address || "0.0.0.0"), :port => Webrat.configuration.selenium_server_port
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.stop_selenium_server #:nodoc:
|
|
||||||
::Selenium::RemoteControl::RemoteControl.new("0.0.0.0", Webrat.configuration.selenium_server_port, 5).stop unless Webrat.configuration.selenium_server_address
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.start_app_server #:nodoc:
|
|
||||||
pid_file = File.expand_path(RAILS_ROOT + "/tmp/pids/mongrel_selenium.pid")
|
|
||||||
system("mongrel_rails start -d --chdir=#{RAILS_ROOT} --port=#{Webrat.configuration.application_port} --environment=#{Webrat.configuration.application_environment} --pid #{pid_file} &")
|
|
||||||
TCPSocket.wait_for_service :host => Webrat.configuration.application_address, :port => Webrat.configuration.application_port.to_i
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.stop_app_server #:nodoc:
|
|
||||||
pid_file = File.expand_path(RAILS_ROOT + "/tmp/pids/mongrel_selenium.pid")
|
|
||||||
system "mongrel_rails stop -c #{RAILS_ROOT} --pid #{pid_file}"
|
|
||||||
end
|
|
||||||
|
|
||||||
# To use Webrat's Selenium support, you'll need the selenium-client gem installed.
|
# To use Webrat's Selenium support, you'll need the selenium-client gem installed.
|
||||||
# Activate it with (for example, in your <tt>env.rb</tt>):
|
# Activate it with (for example, in your <tt>env.rb</tt>):
|
||||||
#
|
#
|
||||||
|
@ -55,11 +25,25 @@ module Webrat
|
||||||
# selenium.dragdrop("id=photo_123", "+350, 0")
|
# selenium.dragdrop("id=photo_123", "+350, 0")
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# == Auto-starting of the mongrel and java server
|
# == Choosing the underlying framework to test
|
||||||
|
#
|
||||||
|
# Webrat assumes you're using rails by default but it can also work with sinatra
|
||||||
|
# and merb. To take advantage of this you can use the configuration block to
|
||||||
|
# set the application_framework variable.
|
||||||
|
# require "webrat"
|
||||||
|
#
|
||||||
|
# Webrat.configure do |config|
|
||||||
|
# config.mode = :selenium
|
||||||
|
# config.application_port = 4567
|
||||||
|
# config.application_framework = :sinatra # could also be :merb
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# == Auto-starting of the appserver and java server
|
||||||
#
|
#
|
||||||
# Webrat will automatically start the Selenium Java server process and an instance
|
# Webrat will automatically start the Selenium Java server process and an instance
|
||||||
# of Mongrel when a test is run. The Mongrel will run in the "selenium" environment
|
# of Mongrel when a test is run. The Mongrel will run in the "selenium" environment
|
||||||
# instead of "test", so ensure you've got that defined, and will run on port 3001.
|
# instead of "test", so ensure you've got that defined, and will run on port
|
||||||
|
# Webrat.configuration.application_port.
|
||||||
#
|
#
|
||||||
# == Waiting
|
# == Waiting
|
||||||
#
|
#
|
||||||
|
@ -84,11 +68,3 @@ module Webrat
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module ActionController #:nodoc:
|
|
||||||
IntegrationTest.class_eval do
|
|
||||||
include Webrat::Methods
|
|
||||||
include Webrat::Selenium::Methods
|
|
||||||
include Webrat::Selenium::Matchers
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
module Webrat
|
||||||
|
module Selenium
|
||||||
|
|
||||||
|
class ApplicationServerFactory
|
||||||
|
|
||||||
|
def self.app_server_instance
|
||||||
|
case Webrat.configuration.application_framework
|
||||||
|
when :sinatra
|
||||||
|
require "webrat/selenium/application_servers/sinatra"
|
||||||
|
return Webrat::Selenium::ApplicationServers::Sinatra.new
|
||||||
|
when :merb
|
||||||
|
require "webrat/selenium/application_servers/merb"
|
||||||
|
return Webrat::Selenium::ApplicationServers::Merb.new
|
||||||
|
when :rails
|
||||||
|
require "webrat/selenium/application_servers/rails"
|
||||||
|
return Webrat::Selenium::ApplicationServers::Rails.new
|
||||||
|
when :external
|
||||||
|
require "webrat/selenium/application_servers/external"
|
||||||
|
return Webrat::Selenium::ApplicationServers::External.new
|
||||||
|
else
|
||||||
|
raise WebratError.new(<<-STR)
|
||||||
|
Unknown Webrat application_framework: #{Webrat.configuration.application_framework.inspect}
|
||||||
|
|
||||||
|
Please ensure you have a Webrat configuration block that specifies an application_framework
|
||||||
|
in your test_helper.rb, spec_helper.rb, or env.rb (for Cucumber).
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
Webrat.configure do |config|
|
||||||
|
# ...
|
||||||
|
config.application_framework = :rails
|
||||||
|
end
|
||||||
|
STR
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
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"
|
|
@ -0,0 +1,46 @@
|
||||||
|
require "webrat/selenium/silence_stream"
|
||||||
|
|
||||||
|
module Webrat
|
||||||
|
module Selenium
|
||||||
|
module ApplicationServers
|
||||||
|
class Base
|
||||||
|
include Webrat::Selenium::SilenceStream
|
||||||
|
|
||||||
|
def boot
|
||||||
|
start
|
||||||
|
wait
|
||||||
|
stop_at_exit
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop_at_exit
|
||||||
|
at_exit do
|
||||||
|
stop
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def wait
|
||||||
|
$stderr.print "==> Waiting for #{Webrat.configuration.application_framework} application server on port #{Webrat.configuration.application_port}... "
|
||||||
|
wait_for_socket
|
||||||
|
$stderr.print "Ready!\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def wait_for_socket
|
||||||
|
silence_stream(STDOUT) do
|
||||||
|
TCPSocket.wait_for_service_with_timeout \
|
||||||
|
:host => "0.0.0.0",
|
||||||
|
:port => Webrat.configuration.application_port.to_i,
|
||||||
|
:timeout => 30 # seconds
|
||||||
|
end
|
||||||
|
rescue SocketError
|
||||||
|
fail
|
||||||
|
end
|
||||||
|
|
||||||
|
def prepare_pid_file(file_path, pid_file_name)
|
||||||
|
FileUtils.mkdir_p File.expand_path(file_path)
|
||||||
|
File.expand_path("#{file_path}/#{pid_file_name}")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,26 @@
|
||||||
|
require "webrat/selenium/application_servers/base"
|
||||||
|
|
||||||
|
module Webrat
|
||||||
|
module Selenium
|
||||||
|
module ApplicationServers
|
||||||
|
class External < Webrat::Selenium::ApplicationServers::Base
|
||||||
|
def start
|
||||||
|
warn "Webrat Ignoring Start Of Application Server Due to External Mode"
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop
|
||||||
|
end
|
||||||
|
|
||||||
|
def fail
|
||||||
|
end
|
||||||
|
|
||||||
|
def pid_file
|
||||||
|
end
|
||||||
|
|
||||||
|
def wait
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,50 @@
|
||||||
|
require "webrat/selenium/application_servers/base"
|
||||||
|
|
||||||
|
module Webrat
|
||||||
|
module Selenium
|
||||||
|
module ApplicationServers
|
||||||
|
class Merb < Webrat::Selenium::ApplicationServers::Base
|
||||||
|
|
||||||
|
def start
|
||||||
|
system start_command
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop
|
||||||
|
silence_stream(STDOUT) do
|
||||||
|
pid = File.read(pid_file)
|
||||||
|
system("kill -9 #{pid}")
|
||||||
|
FileUtils.rm_f pid_file
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def fail
|
||||||
|
$stderr.puts
|
||||||
|
$stderr.puts
|
||||||
|
$stderr.puts "==> Failed to boot the Merb application server... exiting!"
|
||||||
|
$stderr.puts
|
||||||
|
$stderr.puts "Verify you can start a Merb server on port #{Webrat.configuration.application_port} with the following command:"
|
||||||
|
$stderr.puts
|
||||||
|
$stderr.puts " #{start_command}"
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
|
||||||
|
def pid_file
|
||||||
|
"log/merb.#{Webrat.configuration.application_port}.pid"
|
||||||
|
end
|
||||||
|
|
||||||
|
def start_command
|
||||||
|
"#{merb_command} -d -p #{Webrat.configuration.application_port} -e #{Webrat.configuration.application_environment}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def merb_command
|
||||||
|
if File.exist?('bin/merb')
|
||||||
|
merb_cmd = 'bin/merb'
|
||||||
|
else
|
||||||
|
merb_cmd = 'merb'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,44 @@
|
||||||
|
require "webrat/selenium/application_servers/base"
|
||||||
|
|
||||||
|
module Webrat
|
||||||
|
module Selenium
|
||||||
|
module ApplicationServers
|
||||||
|
class Rails < Webrat::Selenium::ApplicationServers::Base
|
||||||
|
|
||||||
|
def start
|
||||||
|
system start_command
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop
|
||||||
|
silence_stream(STDOUT) do
|
||||||
|
system stop_command
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def fail
|
||||||
|
$stderr.puts
|
||||||
|
$stderr.puts
|
||||||
|
$stderr.puts "==> Failed to boot the Rails application server... exiting!"
|
||||||
|
$stderr.puts
|
||||||
|
$stderr.puts "Verify you can start a Rails server on port #{Webrat.configuration.application_port} with the following command:"
|
||||||
|
$stderr.puts
|
||||||
|
$stderr.puts " #{start_command}"
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
|
||||||
|
def pid_file
|
||||||
|
prepare_pid_file("#{RAILS_ROOT}/tmp/pids", "mongrel_selenium.pid")
|
||||||
|
end
|
||||||
|
|
||||||
|
def start_command
|
||||||
|
"mongrel_rails start -d --chdir='#{RAILS_ROOT}' --port=#{Webrat.configuration.application_port} --environment=#{Webrat.configuration.application_environment} --pid #{pid_file} &"
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop_command
|
||||||
|
"mongrel_rails stop -c #{RAILS_ROOT} --pid #{pid_file}"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,37 @@
|
||||||
|
require "webrat/selenium/application_servers/base"
|
||||||
|
|
||||||
|
module Webrat
|
||||||
|
module Selenium
|
||||||
|
module ApplicationServers
|
||||||
|
class Sinatra < Webrat::Selenium::ApplicationServers::Base
|
||||||
|
|
||||||
|
def start
|
||||||
|
fork do
|
||||||
|
File.open('rack.pid', 'w') { |fp| fp.write Process.pid }
|
||||||
|
exec 'rackup', File.expand_path(Dir.pwd + '/config.ru'), '-p', Webrat.configuration.application_port.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop
|
||||||
|
silence_stream(STDOUT) do
|
||||||
|
pid = File.read(pid_file)
|
||||||
|
system("kill -9 #{pid}")
|
||||||
|
FileUtils.rm_f pid_file
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def fail
|
||||||
|
$stderr.puts
|
||||||
|
$stderr.puts
|
||||||
|
$stderr.puts "==> Failed to boot the Sinatra application server... exiting!"
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
|
||||||
|
def pid_file
|
||||||
|
prepare_pid_file(Dir.pwd, 'rack.pid')
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,12 +1,19 @@
|
||||||
if (locator == '*') {
|
if (locator == '*') {
|
||||||
return selenium.browserbot.locationStrategies['xpath'].call(this, "//input[@type='submit']", inDocument, inWindow)
|
return selenium.browserbot.locationStrategies['xpath'].call(this, "//input[@type='submit']", inDocument, inWindow)
|
||||||
}
|
}
|
||||||
|
var buttons = inDocument.getElementsByTagName('button');
|
||||||
var inputs = inDocument.getElementsByTagName('input');
|
var inputs = inDocument.getElementsByTagName('input');
|
||||||
return $A(inputs).find(function(candidate){
|
var result = $A(inputs).concat($A(buttons)).find(function(candidate){
|
||||||
inputType = candidate.getAttribute('type');
|
var type = candidate.getAttribute('type');
|
||||||
if (inputType == 'submit' || inputType == 'image') {
|
if (type == 'submit' || type == 'image' || type == 'button') {
|
||||||
var buttonText = $F(candidate);
|
var matches_id = PatternMatcher.matches(locator, candidate.id);
|
||||||
return (PatternMatcher.matches(locator, buttonText));
|
var matches_value = PatternMatcher.matches(locator, candidate.value);
|
||||||
}
|
var matches_html = PatternMatcher.matches(locator, candidate.innerHTML);
|
||||||
return false;
|
var matches_alt = PatternMatcher.matches(locator, candidate.alt);
|
||||||
|
if (matches_id || matches_value || matches_html || matches_alt) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
|
return result;
|
||||||
|
|
|
@ -1,16 +1,48 @@
|
||||||
|
// Credit to: http://simonwillison.net/2006/Jan/20/escape/
|
||||||
|
RegExp.escape = function(text) {
|
||||||
|
if (!arguments.callee.sRE) {
|
||||||
|
var specials = [
|
||||||
|
'/', '.', '*', '+', '?', '|',
|
||||||
|
'(', ')', '[', ']', '{', '}', '\\'
|
||||||
|
];
|
||||||
|
arguments.callee.sRE = new RegExp(
|
||||||
|
'(\\' + specials.join('|\\') + ')', 'g'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return text.replace(arguments.callee.sRE, '\\$1');
|
||||||
|
};
|
||||||
|
|
||||||
var allLabels = inDocument.getElementsByTagName("label");
|
var allLabels = inDocument.getElementsByTagName("label");
|
||||||
|
var regExp = new RegExp('^\\W*' + RegExp.escape(locator) + '(\\b|$)', 'i');
|
||||||
|
|
||||||
var candidateLabels = $A(allLabels).select(function(candidateLabel){
|
var candidateLabels = $A(allLabels).select(function(candidateLabel){
|
||||||
var regExp = new RegExp('^' + locator + '\\b', 'i');
|
|
||||||
var labelText = getText(candidateLabel).strip();
|
var labelText = getText(candidateLabel).strip();
|
||||||
return (labelText.search(regExp) >= 0);
|
return (labelText.search(regExp) >= 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (candidateLabels.length == 0) {
|
if (candidateLabels.length == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
candidateLabels = candidateLabels.sortBy(function(s) { return s.length * -1; }); //reverse length sort
|
|
||||||
|
//reverse length sort
|
||||||
|
candidateLabels = candidateLabels.sortBy(function(s) {
|
||||||
|
return s.length * -1;
|
||||||
|
});
|
||||||
|
|
||||||
var locatedLabel = candidateLabels.first();
|
var locatedLabel = candidateLabels.first();
|
||||||
var labelFor = locatedLabel.getAttribute('for');
|
var labelFor = null;
|
||||||
if ((labelFor == null) && (locatedLabel.hasChildNodes())) {
|
|
||||||
return locatedLabel.firstChild; //TODO: should find the first form field, not just any node
|
if (locatedLabel.getAttribute('for')) {
|
||||||
|
labelFor = locatedLabel.getAttribute('for');
|
||||||
|
} else if (locatedLabel.attributes['for']) { // IE
|
||||||
|
labelFor = locatedLabel.attributes['for'].nodeValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((labelFor == null) && (locatedLabel.hasChildNodes())) {
|
||||||
|
return locatedLabel.getElementsByTagName('button')[0]
|
||||||
|
|| locatedLabel.getElementsByTagName('input')[0]
|
||||||
|
|| locatedLabel.getElementsByTagName('textarea')[0]
|
||||||
|
|| locatedLabel.getElementsByTagName('select')[0];
|
||||||
|
}
|
||||||
|
|
||||||
return selenium.browserbot.locationStrategies['id'].call(this, labelFor, inDocument, inWindow);
|
return selenium.browserbot.locationStrategies['id'].call(this, labelFor, inDocument, inWindow);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
var locationStrategies = selenium.browserbot.locationStrategies;
|
var locationStrategies = selenium.browserbot.locationStrategies;
|
||||||
|
|
||||||
return locationStrategies['id'].call(this, locator, inDocument, inWindow)
|
return locationStrategies['id'].call(this, locator, inDocument, inWindow)
|
||||||
|| locationStrategies['name'].call(this, locator, inDocument, inWindow)
|
|| locationStrategies['name'].call(this, locator, inDocument, inWindow)
|
||||||
|| locationStrategies['label'].call(this, locator, inDocument, inWindow)
|
|| locationStrategies['label'].call(this, locator, inDocument, inWindow)
|
||||||
|
|
|
@ -1,9 +1,32 @@
|
||||||
var links = inDocument.getElementsByTagName('a');
|
var links = inDocument.getElementsByTagName('a');
|
||||||
|
|
||||||
var candidateLinks = $A(links).select(function(candidateLink) {
|
var candidateLinks = $A(links).select(function(candidateLink) {
|
||||||
return PatternMatcher.matches(locator, getText(candidateLink));
|
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) {
|
if (candidateLinks.length == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
candidateLinks = candidateLinks.sortBy(function(s) { return s.length * -1; }); //reverse length sort
|
|
||||||
|
//reverse length sort
|
||||||
|
candidateLinks = candidateLinks.sortBy(function(s) {
|
||||||
|
return s.length * -1;
|
||||||
|
});
|
||||||
|
|
||||||
return candidateLinks.first();
|
return candidateLinks.first();
|
||||||
|
|
|
@ -1,146 +1,4 @@
|
||||||
module Webrat
|
require "webrat/selenium/matchers/have_xpath"
|
||||||
module Selenium
|
require "webrat/selenium/matchers/have_selector"
|
||||||
module Matchers
|
# require "webrat/selenium/matchers/have_tag"
|
||||||
|
require "webrat/selenium/matchers/have_content"
|
||||||
class HaveXpath
|
|
||||||
def initialize(expected)
|
|
||||||
@expected = expected
|
|
||||||
end
|
|
||||||
|
|
||||||
def matches?(response)
|
|
||||||
response.session.wait_for do
|
|
||||||
response.selenium.is_element_present("xpath=#{@expected}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# ==== Returns
|
|
||||||
# String:: The failure message.
|
|
||||||
def failure_message
|
|
||||||
"expected following text to match xpath #{@expected}:\n#{@document}"
|
|
||||||
end
|
|
||||||
|
|
||||||
# ==== Returns
|
|
||||||
# String:: The failure message to be displayed in negative matches.
|
|
||||||
def negative_failure_message
|
|
||||||
"expected following text to not match xpath #{@expected}:\n#{@document}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def have_xpath(xpath)
|
|
||||||
HaveXpath.new(xpath)
|
|
||||||
end
|
|
||||||
|
|
||||||
def assert_have_xpath(expected)
|
|
||||||
hs = HaveXpath.new(expected)
|
|
||||||
assert hs.matches?(response), hs.failure_message
|
|
||||||
end
|
|
||||||
|
|
||||||
def assert_have_no_xpath(expected)
|
|
||||||
hs = HaveXpath.new(expected)
|
|
||||||
assert !hs.matches?(response), hs.negative_failure_message
|
|
||||||
end
|
|
||||||
|
|
||||||
class HaveSelector
|
|
||||||
def initialize(expected)
|
|
||||||
@expected = expected
|
|
||||||
end
|
|
||||||
|
|
||||||
def matches?(response)
|
|
||||||
response.session.wait_for do
|
|
||||||
response.selenium.is_element_present("css=#{@expected}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# ==== Returns
|
|
||||||
# String:: The failure message.
|
|
||||||
def failure_message
|
|
||||||
"expected following text to match selector #{@expected}:\n#{@document}"
|
|
||||||
end
|
|
||||||
|
|
||||||
# ==== Returns
|
|
||||||
# String:: The failure message to be displayed in negative matches.
|
|
||||||
def negative_failure_message
|
|
||||||
"expected following text to not match selector #{@expected}:\n#{@document}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def have_selector(content)
|
|
||||||
HaveSelector.new(content)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Asserts that the body of the response contains
|
|
||||||
# the supplied selector
|
|
||||||
def assert_have_selector(expected)
|
|
||||||
hs = HaveSelector.new(expected)
|
|
||||||
assert hs.matches?(response), hs.failure_message
|
|
||||||
end
|
|
||||||
|
|
||||||
# Asserts that the body of the response
|
|
||||||
# does not contain the supplied string or regepx
|
|
||||||
def assert_have_no_selector(expected)
|
|
||||||
hs = HaveSelector.new(expected)
|
|
||||||
assert !hs.matches?(response), hs.negative_failure_message
|
|
||||||
end
|
|
||||||
|
|
||||||
class HasContent #:nodoc:
|
|
||||||
def initialize(content)
|
|
||||||
@content = content
|
|
||||||
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
|
|
||||||
end
|
|
||||||
|
|
||||||
# ==== Returns
|
|
||||||
# String:: The failure message.
|
|
||||||
def failure_message
|
|
||||||
"expected the following element's content to #{content_message}:\n#{@element}"
|
|
||||||
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}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def content_message
|
|
||||||
case @content
|
|
||||||
when String
|
|
||||||
"include \"#{@content}\""
|
|
||||||
when Regexp
|
|
||||||
"match #{@content.inspect}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Matches the contents of an HTML document with
|
|
||||||
# whatever string is supplied
|
|
||||||
def contain(content)
|
|
||||||
HasContent.new(content)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Asserts that the body of the response contain
|
|
||||||
# the supplied string or regexp
|
|
||||||
def assert_contain(content)
|
|
||||||
hc = HasContent.new(content)
|
|
||||||
assert hc.matches?(response), hc.failure_message
|
|
||||||
end
|
|
||||||
|
|
||||||
# Asserts that the body of the response
|
|
||||||
# does not contain the supplied string or regepx
|
|
||||||
def assert_not_contain(content)
|
|
||||||
hc = HasContent.new(content)
|
|
||||||
assert !hc.matches?(response), hc.negative_failure_message
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
module Webrat
|
||||||
|
module Selenium
|
||||||
|
module Matchers
|
||||||
|
class HasContent #:nodoc:
|
||||||
|
def initialize(content)
|
||||||
|
@content = content
|
||||||
|
end
|
||||||
|
|
||||||
|
def matches?(response)
|
||||||
|
response.session.wait_for do
|
||||||
|
response.selenium.is_text_present(text_finder)
|
||||||
|
end
|
||||||
|
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 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 response to not #{content_message}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def content_message
|
||||||
|
case @content
|
||||||
|
when String
|
||||||
|
"include \"#{@content}\""
|
||||||
|
when Regexp
|
||||||
|
"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
|
||||||
|
# whatever string is supplied
|
||||||
|
def contain(content)
|
||||||
|
HasContent.new(content)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Asserts that the body of the response contain
|
||||||
|
# the supplied string or regexp
|
||||||
|
def assert_contain(content)
|
||||||
|
hc = HasContent.new(content)
|
||||||
|
assert hc.matches?(response), hc.failure_message
|
||||||
|
end
|
||||||
|
|
||||||
|
# Asserts that the body of the response
|
||||||
|
# does not contain the supplied string or regepx
|
||||||
|
def assert_not_contain(content)
|
||||||
|
hc = HasContent.new(content)
|
||||||
|
assert !hc.matches?(response), hc.negative_failure_message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,57 @@
|
||||||
|
module Webrat
|
||||||
|
module Selenium
|
||||||
|
module Matchers
|
||||||
|
class HaveSelector
|
||||||
|
def initialize(expected)
|
||||||
|
@expected = expected
|
||||||
|
end
|
||||||
|
|
||||||
|
def matches?(response)
|
||||||
|
response.session.wait_for do
|
||||||
|
response.selenium.is_element_present("css=#{@expected}")
|
||||||
|
end
|
||||||
|
rescue Webrat::TimeoutError
|
||||||
|
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
|
||||||
|
"expected following text to match selector #{@expected}:\n#{@document}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# ==== Returns
|
||||||
|
# String:: The failure message to be displayed in negative matches.
|
||||||
|
def negative_failure_message
|
||||||
|
"expected following text to not match selector #{@expected}:\n#{@document}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def have_selector(content)
|
||||||
|
HaveSelector.new(content)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Asserts that the body of the response contains
|
||||||
|
# the supplied selector
|
||||||
|
def assert_have_selector(expected)
|
||||||
|
hs = HaveSelector.new(expected)
|
||||||
|
assert hs.matches?(response), hs.failure_message
|
||||||
|
end
|
||||||
|
|
||||||
|
# Asserts that the body of the response
|
||||||
|
# does not contain the supplied string or regepx
|
||||||
|
def assert_have_no_selector(expected)
|
||||||
|
hs = HaveSelector.new(expected)
|
||||||
|
assert !hs.matches?(response), hs.negative_failure_message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,72 @@
|
||||||
|
module Webrat
|
||||||
|
module Selenium
|
||||||
|
module Matchers
|
||||||
|
|
||||||
|
class HaveTag < HaveSelector #:nodoc:
|
||||||
|
# ==== Returns
|
||||||
|
# String:: The failure message.
|
||||||
|
def failure_message
|
||||||
|
"expected following output to contain a #{tag_inspect} tag:\n#{@document}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# ==== Returns
|
||||||
|
# String:: The failure message to be displayed in negative matches.
|
||||||
|
def negative_failure_message
|
||||||
|
"expected following output to omit a #{tag_inspect}:\n#{@document}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def tag_inspect
|
||||||
|
options = @expected.last.dup
|
||||||
|
content = options.delete(:content)
|
||||||
|
|
||||||
|
html = "<#{@expected.first}"
|
||||||
|
options.each do |k,v|
|
||||||
|
html << " #{k}='#{v}'"
|
||||||
|
end
|
||||||
|
|
||||||
|
if content
|
||||||
|
html << ">#{content}</#{@expected.first}>"
|
||||||
|
else
|
||||||
|
html << "/>"
|
||||||
|
end
|
||||||
|
|
||||||
|
html
|
||||||
|
end
|
||||||
|
|
||||||
|
def query
|
||||||
|
options = @expected.last.dup
|
||||||
|
selector = @expected.first.to_s
|
||||||
|
|
||||||
|
selector << ":contains('#{options.delete(:content)}')" if options[:content]
|
||||||
|
|
||||||
|
options.each do |key, value|
|
||||||
|
selector << "[#{key}='#{value}']"
|
||||||
|
end
|
||||||
|
|
||||||
|
Nokogiri::CSS.parse(selector).map { |ast| ast.to_xpath }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def have_tag(name, attributes = {}, &block)
|
||||||
|
HaveTag.new([name, attributes], &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
alias_method :match_tag, :have_tag
|
||||||
|
|
||||||
|
# Asserts that the body of the response contains
|
||||||
|
# the supplied tag with the associated selectors
|
||||||
|
def assert_have_tag(name, attributes = {})
|
||||||
|
ht = HaveTag.new([name, attributes])
|
||||||
|
assert ht.matches?(response), ht.failure_message
|
||||||
|
end
|
||||||
|
|
||||||
|
# Asserts that the body of the response
|
||||||
|
# does not contain the supplied string or regepx
|
||||||
|
def assert_have_no_tag(name, attributes = {})
|
||||||
|
ht = HaveTag.new([name, attributes])
|
||||||
|
assert !ht.matches?(response), ht.negative_failure_message
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,53 @@
|
||||||
|
module Webrat
|
||||||
|
module Selenium
|
||||||
|
module Matchers
|
||||||
|
class HaveXpath
|
||||||
|
def initialize(expected)
|
||||||
|
@expected = expected
|
||||||
|
end
|
||||||
|
|
||||||
|
def matches?(response)
|
||||||
|
response.session.wait_for do
|
||||||
|
response.selenium.is_element_present("xpath=#{@expected}")
|
||||||
|
end
|
||||||
|
rescue Webrat::TimeoutError
|
||||||
|
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
|
||||||
|
"expected following text to match xpath #{@expected}:\n#{@document}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# ==== Returns
|
||||||
|
# String:: The failure message to be displayed in negative matches.
|
||||||
|
def negative_failure_message
|
||||||
|
"expected following text to not match xpath #{@expected}:\n#{@document}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def have_xpath(xpath)
|
||||||
|
HaveXpath.new(xpath)
|
||||||
|
end
|
||||||
|
|
||||||
|
def assert_have_xpath(expected)
|
||||||
|
hs = HaveXpath.new(expected)
|
||||||
|
assert hs.matches?(response), hs.failure_message
|
||||||
|
end
|
||||||
|
|
||||||
|
def assert_have_no_xpath(expected)
|
||||||
|
hs = HaveXpath.new(expected)
|
||||||
|
assert !hs.matches?(response), hs.negative_failure_message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,89 @@
|
||||||
|
module Webrat
|
||||||
|
module Selenium
|
||||||
|
|
||||||
|
class SeleniumRCServer
|
||||||
|
|
||||||
|
include Webrat::Selenium::SilenceStream
|
||||||
|
|
||||||
|
def self.boot
|
||||||
|
new.boot
|
||||||
|
end
|
||||||
|
|
||||||
|
def boot
|
||||||
|
return if selenium_grid?
|
||||||
|
|
||||||
|
start
|
||||||
|
wait
|
||||||
|
stop_at_exit
|
||||||
|
end
|
||||||
|
|
||||||
|
def start
|
||||||
|
silence_stream(STDOUT) do
|
||||||
|
remote_control.start :background => true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop_at_exit
|
||||||
|
at_exit do
|
||||||
|
stop
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
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,
|
||||||
|
server_options)
|
||||||
|
|
||||||
|
@remote_control.jar_file = jar_path
|
||||||
|
|
||||||
|
return @remote_control
|
||||||
|
end
|
||||||
|
|
||||||
|
def jar_path
|
||||||
|
File.expand_path(__FILE__ + "../../../../../vendor/selenium-server.jar")
|
||||||
|
end
|
||||||
|
|
||||||
|
def selenium_grid?
|
||||||
|
Webrat.configuration.selenium_server_address
|
||||||
|
end
|
||||||
|
|
||||||
|
def wait
|
||||||
|
$stderr.print "==> Waiting for Selenium RC server on port #{Webrat.configuration.selenium_server_port}... "
|
||||||
|
wait_for_socket
|
||||||
|
$stderr.print "Ready!\n"
|
||||||
|
rescue SocketError
|
||||||
|
fail
|
||||||
|
end
|
||||||
|
|
||||||
|
def wait_for_socket
|
||||||
|
silence_stream(STDOUT) do
|
||||||
|
TCPSocket.wait_for_service_with_timeout \
|
||||||
|
:host => (Webrat.configuration.selenium_server_address || "0.0.0.0"),
|
||||||
|
:port => Webrat.configuration.selenium_server_port,
|
||||||
|
:timeout => 45 # seconds
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def fail
|
||||||
|
$stderr.puts
|
||||||
|
$stderr.puts
|
||||||
|
$stderr.puts "==> Failed to boot the Selenium RC server... exiting!"
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop
|
||||||
|
silence_stream(STDOUT) do
|
||||||
|
::Selenium::RemoteControl::RemoteControl.new("0.0.0.0",
|
||||||
|
Webrat.configuration.selenium_server_port,
|
||||||
|
:timeout => 5).stop
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,4 +1,14 @@
|
||||||
require "webrat/core/save_and_open_page"
|
require "webrat/core/save_and_open_page"
|
||||||
|
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
|
module Webrat
|
||||||
class TimeoutError < WebratError
|
class TimeoutError < WebratError
|
||||||
|
@ -20,6 +30,7 @@ module Webrat
|
||||||
|
|
||||||
class SeleniumSession
|
class SeleniumSession
|
||||||
include Webrat::SaveAndOpenPage
|
include Webrat::SaveAndOpenPage
|
||||||
|
include Webrat::Selenium::SilenceStream
|
||||||
|
|
||||||
def initialize(*args) # :nodoc:
|
def initialize(*args) # :nodoc:
|
||||||
end
|
end
|
||||||
|
@ -38,8 +49,8 @@ module Webrat
|
||||||
webrat_deprecate :visits, :visit
|
webrat_deprecate :visits, :visit
|
||||||
|
|
||||||
def fill_in(field_identifier, options)
|
def fill_in(field_identifier, options)
|
||||||
locator = "webrat=#{Regexp.escape(field_identifier)}"
|
locator = "webrat=#{field_identifier}"
|
||||||
selenium.wait_for_element locator, 5
|
selenium.wait_for_element locator, :timeout_in_seconds => 5
|
||||||
selenium.type(locator, "#{options[:with]}")
|
selenium.type(locator, "#{options[:with]}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -53,6 +64,10 @@ module Webrat
|
||||||
selenium.get_html_source
|
selenium.get_html_source
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def current_url
|
||||||
|
selenium.location
|
||||||
|
end
|
||||||
|
|
||||||
def click_button(button_text_or_regexp = nil, options = {})
|
def click_button(button_text_or_regexp = nil, options = {})
|
||||||
if button_text_or_regexp.is_a?(Hash) && options == {}
|
if button_text_or_regexp.is_a?(Hash) && options == {}
|
||||||
pattern, options = nil, button_text_or_regexp
|
pattern, options = nil, button_text_or_regexp
|
||||||
|
@ -62,16 +77,21 @@ module Webrat
|
||||||
pattern ||= '*'
|
pattern ||= '*'
|
||||||
locator = "button=#{pattern}"
|
locator = "button=#{pattern}"
|
||||||
|
|
||||||
selenium.wait_for_element locator, 5
|
selenium.wait_for_element locator, :timeout_in_seconds => 5
|
||||||
selenium.click locator
|
selenium.click locator
|
||||||
end
|
end
|
||||||
|
|
||||||
webrat_deprecate :clicks_button, :click_button
|
webrat_deprecate :clicks_button, :click_button
|
||||||
|
|
||||||
def click_link(link_text_or_regexp, options = {})
|
def click_link(link_text_or_regexp, options = {})
|
||||||
pattern = adjust_if_regexp(link_text_or_regexp)
|
if link_text_or_regexp.is_a?(Regexp)
|
||||||
|
pattern = "evalregex:#{link_text_or_regexp.inspect}"
|
||||||
|
else
|
||||||
|
pattern = link_text_or_regexp.to_s
|
||||||
|
end
|
||||||
|
|
||||||
locator = "webratlink=#{pattern}"
|
locator = "webratlink=#{pattern}"
|
||||||
selenium.wait_for_element locator, 5
|
selenium.wait_for_element locator, :timeout_in_seconds => 5
|
||||||
selenium.click locator
|
selenium.click locator
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -79,7 +99,7 @@ module Webrat
|
||||||
|
|
||||||
def click_link_within(selector, link_text, options = {})
|
def click_link_within(selector, link_text, options = {})
|
||||||
locator = "webratlinkwithin=#{selector}|#{link_text}"
|
locator = "webratlinkwithin=#{selector}|#{link_text}"
|
||||||
selenium.wait_for_element locator, 5
|
selenium.wait_for_element locator, :timeout_in_seconds => 5
|
||||||
selenium.click locator
|
selenium.click locator
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -94,7 +114,7 @@ module Webrat
|
||||||
select_locator = "webratselectwithoption=#{option_text}"
|
select_locator = "webratselectwithoption=#{option_text}"
|
||||||
end
|
end
|
||||||
|
|
||||||
selenium.wait_for_element select_locator, 5
|
selenium.wait_for_element select_locator, :timeout_in_seconds => 5
|
||||||
selenium.select(select_locator, option_text)
|
selenium.select(select_locator, option_text)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -102,7 +122,7 @@ module Webrat
|
||||||
|
|
||||||
def choose(label_text)
|
def choose(label_text)
|
||||||
locator = "webrat=#{label_text}"
|
locator = "webrat=#{label_text}"
|
||||||
selenium.wait_for_element locator, 5
|
selenium.wait_for_element locator, :timeout_in_seconds => 5
|
||||||
selenium.click locator
|
selenium.click locator
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -110,9 +130,10 @@ module Webrat
|
||||||
|
|
||||||
def check(label_text)
|
def check(label_text)
|
||||||
locator = "webrat=#{label_text}"
|
locator = "webrat=#{label_text}"
|
||||||
selenium.wait_for_element locator, 5
|
selenium.wait_for_element locator, :timeout_in_seconds => 5
|
||||||
selenium.check locator
|
selenium.click locator
|
||||||
end
|
end
|
||||||
|
alias_method :uncheck, :check
|
||||||
|
|
||||||
webrat_deprecate :checks, :check
|
webrat_deprecate :checks, :check
|
||||||
|
|
||||||
|
@ -142,8 +163,10 @@ module Webrat
|
||||||
|
|
||||||
begin
|
begin
|
||||||
value = yield
|
value = yield
|
||||||
rescue ::Spec::Expectations::ExpectationNotMetError, ::Selenium::CommandError, Webrat::WebratError
|
rescue Exception => e
|
||||||
value = nil
|
unless is_ignorable_wait_for_exception?(e)
|
||||||
|
raise e
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return value if value
|
return value if value
|
||||||
|
@ -151,7 +174,19 @@ module Webrat
|
||||||
sleep 0.25
|
sleep 0.25
|
||||||
end
|
end
|
||||||
|
|
||||||
raise Webrat::TimeoutError.new(message + " (after #{timeout} sec)")
|
error_message = "#{message} (after #{timeout} sec)"
|
||||||
|
|
||||||
|
if $browser && Webrat.configuration.selenium_verbose_output
|
||||||
|
error_message += <<-EOS
|
||||||
|
|
||||||
|
|
||||||
|
HTML of the page was:
|
||||||
|
|
||||||
|
#{selenium.get_html_source}"
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
|
||||||
|
raise Webrat::TimeoutError.new(error_message)
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -165,29 +200,34 @@ module Webrat
|
||||||
|
|
||||||
|
|
||||||
def save_and_open_screengrab
|
def save_and_open_screengrab
|
||||||
return unless File.exist?(saved_page_dir)
|
return unless File.exist?(Webrat.configuration.saved_pages_dir)
|
||||||
|
|
||||||
filename = "#{saved_page_dir}/webrat-#{Time.now.to_i}.png"
|
filename = "#{Webrat.configuration.saved_pages_dir}/webrat-#{Time.now.to_i}.png"
|
||||||
|
|
||||||
if $browser.chrome_backend?
|
if $browser.chrome_backend?
|
||||||
$browser.capture_entire_page_screenshot(filename, '')
|
$browser.capture_entire_page_screenshot(filename, '')
|
||||||
else
|
else
|
||||||
$browser.capture_screenshot(filename)
|
$browser.capture_screenshot(filename)
|
||||||
end
|
end
|
||||||
open_in_browser(filename)
|
open_in_browser(filename)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
def is_ignorable_wait_for_exception?(exception) #:nodoc:
|
||||||
|
if defined?(::Spec::Expectations::ExpectationNotMetError)
|
||||||
|
return true if exception.class == ::Spec::Expectations::ExpectationNotMetError
|
||||||
|
end
|
||||||
|
return true if [::Selenium::CommandError, Webrat::WebratError].include?(exception.class)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
def setup #:nodoc:
|
def setup #:nodoc:
|
||||||
silence_stream(STDOUT) do
|
Webrat::Selenium::SeleniumRCServer.boot
|
||||||
Webrat.start_selenium_server
|
Webrat::Selenium::ApplicationServerFactory.app_server_instance.boot
|
||||||
Webrat.start_app_server
|
|
||||||
end
|
|
||||||
|
|
||||||
create_browser
|
create_browser
|
||||||
$browser.start
|
$browser.start
|
||||||
teardown_at_exit
|
|
||||||
|
|
||||||
extend_selenium
|
extend_selenium
|
||||||
define_location_strategies
|
define_location_strategies
|
||||||
|
@ -197,16 +237,12 @@ module Webrat
|
||||||
|
|
||||||
def create_browser
|
def create_browser
|
||||||
$browser = ::Selenium::Client::Driver.new(Webrat.configuration.selenium_server_address || "localhost",
|
$browser = ::Selenium::Client::Driver.new(Webrat.configuration.selenium_server_address || "localhost",
|
||||||
Webrat.configuration.selenium_server_port, Webrat.configuration.selenium_browser_key, "http://#{Webrat.configuration.application_address}:#{Webrat.configuration.application_port}")
|
Webrat.configuration.selenium_server_port, Webrat.configuration.selenium_browser_key, "http://#{Webrat.configuration.application_address}:#{Webrat.configuration.application_port_for_selenium}")
|
||||||
$browser.set_speed(0) unless Webrat.configuration.selenium_server_address
|
$browser.set_speed(0) unless Webrat.configuration.selenium_server_address
|
||||||
end
|
|
||||||
|
|
||||||
def teardown_at_exit #:nodoc:
|
|
||||||
at_exit do
|
at_exit do
|
||||||
silence_stream(STDOUT) do
|
silence_stream(STDOUT) do
|
||||||
$browser.stop
|
$browser.stop
|
||||||
Webrat.stop_app_server
|
|
||||||
Webrat.stop_selenium_server
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
module Webrat
|
||||||
|
module Selenium
|
||||||
|
module SilenceStream
|
||||||
|
# active_support already defines silence_stream, no need to do that again if it's already present.
|
||||||
|
# http://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/kernel/reporting.rb
|
||||||
|
unless Kernel.respond_to?(:silence_stream)
|
||||||
|
def silence_stream(stream)
|
||||||
|
old_stream = stream.dup
|
||||||
|
stream.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null')
|
||||||
|
stream.sync = true
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
stream.reopen(old_stream)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,29 +0,0 @@
|
||||||
require 'webrat/rack'
|
|
||||||
require 'sinatra'
|
|
||||||
require 'sinatra/test/methods'
|
|
||||||
|
|
||||||
class Sinatra::Application
|
|
||||||
# Override this to prevent Sinatra from barfing on the options passed from RSpec
|
|
||||||
def self.load_default_options_from_command_line!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
disable :run
|
|
||||||
disable :reload
|
|
||||||
|
|
||||||
module Webrat
|
|
||||||
class SinatraSession < RackSession #:nodoc:
|
|
||||||
include Sinatra::Test::Methods
|
|
||||||
|
|
||||||
attr_reader :request, :response
|
|
||||||
|
|
||||||
%w(get head post put delete).each do |verb|
|
|
||||||
define_method(verb) do |*args| # (path, data, headers = nil)
|
|
||||||
path, data, headers = *args
|
|
||||||
data = data.inject({}) {|data, (key,value)| data[key] = Rack::Utils.unescape(value); data }
|
|
||||||
params = data.merge(:env => headers || {})
|
|
||||||
self.__send__("#{verb}_it", path, params)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,14 +1,13 @@
|
||||||
module Webrat #:nodoc:
|
module Webrat #:nodoc:
|
||||||
def self.session_class #:nodoc:
|
def self.adapter_class #:nodoc:
|
||||||
TestSession
|
TestAdapter
|
||||||
end
|
end
|
||||||
|
|
||||||
class TestSession < Session #:nodoc:
|
class TestAdapter #:nodoc:
|
||||||
attr_accessor :response_body
|
attr_accessor :response_body
|
||||||
attr_writer :response_code
|
attr_writer :response_code
|
||||||
|
|
||||||
def doc_root
|
def initialize(*args)
|
||||||
File.expand_path(File.join(".", "public"))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def response
|
def response
|
||||||
|
@ -16,7 +15,7 @@ module Webrat #:nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
def response_code
|
def response_code
|
||||||
@response_code || 200
|
@response_code ||= 200
|
||||||
end
|
end
|
||||||
|
|
||||||
def get(url, data, headers = nil)
|
def get(url, data, headers = nil)
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
||||||
|
require "sample_app"
|
||||||
|
run SampleApp
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -4,6 +4,15 @@ class Testing < Application
|
||||||
render
|
render
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def upload
|
||||||
|
case request.method
|
||||||
|
when :get then render
|
||||||
|
when :post then
|
||||||
|
uploaded_file = params[:uploaded_file]
|
||||||
|
render [uploaded_file[:filename], uploaded_file[:tempfile].class.name].inspect
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def submit_form
|
def submit_form
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<h1>Webrat Form</h1>
|
||||||
|
|
||||||
|
<form action="/upload" method="post">
|
||||||
|
<label>
|
||||||
|
File
|
||||||
|
<input type="file" name="uploaded_file" />
|
||||||
|
</label>
|
||||||
|
<input type="submit" value="Upload">
|
||||||
|
</form>
|
|
@ -28,6 +28,7 @@
|
||||||
Merb.logger.info("Compiling routes...")
|
Merb.logger.info("Compiling routes...")
|
||||||
Merb::Router.prepare do
|
Merb::Router.prepare do
|
||||||
match("/").to(:controller => "testing", :action => "show_form")
|
match("/").to(:controller => "testing", :action => "show_form")
|
||||||
|
match("/upload").to(:controller => "testing", :action => "upload")
|
||||||
match("/internal_redirect").to(:controller => "testing", :action => "internal_redirect")
|
match("/internal_redirect").to(:controller => "testing", :action => "internal_redirect")
|
||||||
match("/external_redirect").to(:controller => "testing", :action => "external_redirect")
|
match("/external_redirect").to(:controller => "testing", :action => "external_redirect")
|
||||||
end
|
end
|
|
@ -1,5 +1,7 @@
|
||||||
require "rubygems"
|
require "rubygems"
|
||||||
|
|
||||||
|
$LOAD_PATH.unshift File.dirname(__FILE__) + "/../../../../lib"
|
||||||
|
|
||||||
# Add the local gems dir if found within the app root; any dependencies loaded
|
# 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.
|
# 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?
|
if (local_gem_dir = File.join(File.dirname(__FILE__), '..', 'gems')) && $BUNDLE.nil?
|
||||||
|
|
|
@ -29,4 +29,11 @@ describe "Webrat" do
|
||||||
response = visit "/external_redirect"
|
response = visit "/external_redirect"
|
||||||
response.status.should == 302
|
response.status.should == 302
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "should upload files" do
|
||||||
|
visit "/upload"
|
||||||
|
attach_file "File", __FILE__
|
||||||
|
response = click_button "Upload"
|
||||||
|
response.should contain(%(["webrat_spec.rb", "Tempfile"]))
|
||||||
|
end
|
||||||
end
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
require "rake/testtask"
|
||||||
|
|
||||||
|
Rake::TestTask.new do |t|
|
||||||
|
t.test_files = FileList["test/*_test.rb"]
|
||||||
|
end
|
|
@ -0,0 +1,89 @@
|
||||||
|
require "sinatra/base"
|
||||||
|
|
||||||
|
class RackApp < Sinatra::Base
|
||||||
|
use_in_file_templates!
|
||||||
|
|
||||||
|
get "/" do
|
||||||
|
erb :home
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/go" do
|
||||||
|
erb :go
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/internal_redirect" do
|
||||||
|
redirect "/"
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/external_redirect" do
|
||||||
|
redirect "http://google.com"
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/absolute_redirect" do
|
||||||
|
redirect URI.join(request.url, "foo").to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/foo" do
|
||||||
|
"spam"
|
||||||
|
end
|
||||||
|
|
||||||
|
post "/go" do
|
||||||
|
@user = params[:name]
|
||||||
|
@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__
|
||||||
|
@@ layout
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||||
|
<html>
|
||||||
|
<title>sinatra testing with webrat</title>
|
||||||
|
<body>
|
||||||
|
<%= yield %>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
@@ home
|
||||||
|
<p> visit <a href="/go">there</a></p>
|
||||||
|
|
||||||
|
<form>
|
||||||
|
<label>
|
||||||
|
Prefilled
|
||||||
|
<input type="text" name="prefilled" value="text" />
|
||||||
|
</label>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
@@ go
|
||||||
|
<form method="post" action="/go">
|
||||||
|
<div>
|
||||||
|
<label for="name">Name</label>
|
||||||
|
<input type="text" name="name" id="name">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="email">Email</label>
|
||||||
|
<input type="text" name="email" id="email">
|
||||||
|
</div>
|
||||||
|
<input type="submit" value="Submit" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
@@ 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>
|
|
@ -0,0 +1,20 @@
|
||||||
|
require "test/unit"
|
||||||
|
require "rack/test"
|
||||||
|
# require "redgreen"
|
||||||
|
|
||||||
|
$LOAD_PATH.unshift File.dirname(__FILE__) + "/../../../../lib"
|
||||||
|
require "webrat"
|
||||||
|
require File.dirname(__FILE__) + "/../app"
|
||||||
|
|
||||||
|
Webrat.configure do |config|
|
||||||
|
config.mode = :rack
|
||||||
|
end
|
||||||
|
|
||||||
|
class Test::Unit::TestCase
|
||||||
|
def app
|
||||||
|
Rack::Builder.new {
|
||||||
|
use Rack::Lint
|
||||||
|
run RackApp.new
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,74 @@
|
||||||
|
require "rubygems"
|
||||||
|
require File.dirname(__FILE__) + "/helper"
|
||||||
|
|
||||||
|
class WebratRackTest < Test::Unit::TestCase
|
||||||
|
include Rack::Test::Methods
|
||||||
|
include Webrat::Methods
|
||||||
|
include Webrat::Matchers
|
||||||
|
include Webrat::HaveTagMatcher
|
||||||
|
|
||||||
|
def build_rack_mock_session
|
||||||
|
Rack::MockSession.new(app, "www.example.com")
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_visits_pages
|
||||||
|
visit "/"
|
||||||
|
click_link "there"
|
||||||
|
|
||||||
|
assert_have_tag("form[@method='post'][@action='/go']")
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_submits_form
|
||||||
|
visit "/go"
|
||||||
|
fill_in "Name", :with => "World"
|
||||||
|
fill_in "Email", :with => "world@example.org"
|
||||||
|
click_button "Submit"
|
||||||
|
|
||||||
|
assert_contain "Hello, World"
|
||||||
|
assert_contain "Your email is: world@example.org"
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_check_value_of_field
|
||||||
|
visit "/"
|
||||||
|
assert_equal field_labeled("Prefilled").value, "text"
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_follows_internal_redirects
|
||||||
|
visit "/internal_redirect"
|
||||||
|
assert_contain "visit"
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_does_not_follow_external_redirects
|
||||||
|
visit "/external_redirect"
|
||||||
|
assert last_response.redirect?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_absolute_url_redirect
|
||||||
|
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::RackAdapter.new(rack_test_session)
|
||||||
|
session = Webrat::Session.new(adapter)
|
||||||
|
|
||||||
|
session.visit "/foo"
|
||||||
|
|
||||||
|
assert_equal "spam", session.response_body
|
||||||
|
assert_equal "spam", rack_test_session.last_response.body
|
||||||
|
end
|
||||||
|
end
|
|
@ -1 +1,3 @@
|
||||||
vendor/plugins/webrat
|
vendor/plugins/webrat
|
||||||
|
tmp/pids/*.pid
|
||||||
|
log/*.log
|
||||||
|
|
|
@ -8,3 +8,23 @@ require 'rake/testtask'
|
||||||
require 'rake/rdoctask'
|
require 'rake/rdoctask'
|
||||||
|
|
||||||
require 'tasks/rails'
|
require 'tasks/rails'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace :test_unit do
|
||||||
|
desc "runs the test::unit based tests in webrat mode"
|
||||||
|
task :rails do
|
||||||
|
ENV['WEBRAT_INTEGRATION_MODE'] = 'rails'
|
||||||
|
Rake::Task['test:integration'].execute
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "runs the test::unit based tests in selenium mode"
|
||||||
|
task :selenium do
|
||||||
|
ENV['WEBRAT_INTEGRATION_MODE'] = 'selenium'
|
||||||
|
Rake::Task['test:integration'].execute
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "run both selenium and rails mode Test::Unit suites"
|
||||||
|
task :all => [:rails, :selenium]
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
class ButtonsController < ApplicationController
|
||||||
|
def show
|
||||||
|
end
|
||||||
|
def create
|
||||||
|
render :text => "success"
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,4 @@
|
||||||
|
class FieldsController < ApplicationController
|
||||||
|
def show
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,7 @@
|
||||||
|
class LinksController < ApplicationController
|
||||||
|
def show
|
||||||
|
if params[:value]
|
||||||
|
render :text => "Link:#{params[:value]}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,15 +10,37 @@ class WebratController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def submit
|
def submit
|
||||||
render :text => "OK"
|
render :text => "OK <a href='/' id='link_id'>Test Link Text</a>"
|
||||||
end
|
end
|
||||||
|
|
||||||
def internal_redirect
|
def internal_redirect
|
||||||
redirect_to :submit
|
redirect_to submit_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def infinite_redirect
|
||||||
|
redirect_to infinite_redirect_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def external_redirect
|
def external_redirect
|
||||||
redirect_to "http://google.com"
|
redirect_to "http://google.com"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def host_redirect
|
||||||
|
redirect_to submit_url
|
||||||
|
end
|
||||||
|
|
||||||
|
def before_redirect_form
|
||||||
|
end
|
||||||
|
|
||||||
|
def redirect_to_show_params
|
||||||
|
redirect_to show_params_path(:custom_param => "123")
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_params
|
||||||
|
render :text => params.to_json
|
||||||
|
end
|
||||||
|
|
||||||
|
def within
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
|
@ -0,0 +1,2 @@
|
||||||
|
module ButtonsHelper
|
||||||
|
end
|
|
@ -0,0 +1,2 @@
|
||||||
|
module FieldsHelper
|
||||||
|
end
|
|
@ -0,0 +1,2 @@
|
||||||
|
module LinksHelper
|
||||||
|
end
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue