Commit bc7be0ecc5d4f00ab471ba22776b67080daedb59
1 parent
bf22f099
Exists in
master
and in
1 other branch
adding timecop and fakeweb to testing gems
Showing
49 changed files
with
3562 additions
and
1 deletions
Show diff stats
README.markdown
@@ -20,7 +20,7 @@ This will create a Rails 2.3.2 app with Heroku-recommended code: | @@ -20,7 +20,7 @@ This will create a Rails 2.3.2 app with Heroku-recommended code: | ||
20 | * jQuery for Javascript and Ajax | 20 | * jQuery for Javascript and Ajax |
21 | * Clearance for authentication | 21 | * Clearance for authentication |
22 | * Active Merchant for payment processing | 22 | * Active Merchant for payment processing |
23 | -* Cucumber, Shoulda, Factory Girl, & Mocha for testing | 23 | +* Cucumber, Shoulda, Factory Girl, Mocha, Fakeweb, & Timecop for testing |
24 | * Inherited Resources for RESTful controllers | 24 | * Inherited Resources for RESTful controllers |
25 | * Formtastic for form builders | 25 | * Formtastic for form builders |
26 | * Flutie for CSS framework | 26 | * Flutie for CSS framework |
config/environments/test.rb
@@ -35,12 +35,19 @@ config.gem 'thoughtbot-shoulda', | @@ -35,12 +35,19 @@ config.gem 'thoughtbot-shoulda', | ||
35 | :lib => 'shoulda', | 35 | :lib => 'shoulda', |
36 | :source => 'http://gems.github.com', | 36 | :source => 'http://gems.github.com', |
37 | :version => '>= 2.10.1' | 37 | :version => '>= 2.10.1' |
38 | +config.gem 'jtrupiano-timecop', | ||
39 | + :lib => 'timecop', | ||
40 | + :source => 'http://gems.github.com', | ||
41 | + :version => '0.2.1' | ||
42 | +config.gem 'fakeweb', | ||
43 | + :version => '>= 1.2.5' | ||
38 | 44 | ||
39 | HOST = 'localhost' | 45 | HOST = 'localhost' |
40 | 46 | ||
41 | begin | 47 | begin |
42 | require 'factory_girl' | 48 | require 'factory_girl' |
43 | require 'redgreen' | 49 | require 'redgreen' |
50 | + require 'fakeweb' | ||
44 | rescue LoadError | 51 | rescue LoadError |
45 | end | 52 | end |
46 | 53 |
doc/README_FOR_TEMPLATE
@@ -0,0 +1,122 @@ | @@ -0,0 +1,122 @@ | ||
1 | +--- !ruby/object:Gem::Specification | ||
2 | +name: fakeweb | ||
3 | +version: !ruby/object:Gem::Version | ||
4 | + version: 1.2.5 | ||
5 | +platform: ruby | ||
6 | +authors: | ||
7 | +- Chris Kampmeier | ||
8 | +- Blaine Cook | ||
9 | +autorequire: | ||
10 | +bindir: bin | ||
11 | +cert_chain: [] | ||
12 | + | ||
13 | +date: 2009-07-08 00:00:00 -04:00 | ||
14 | +default_executable: | ||
15 | +dependencies: | ||
16 | +- !ruby/object:Gem::Dependency | ||
17 | + name: mocha | ||
18 | + type: :development | ||
19 | + version_requirement: | ||
20 | + version_requirements: !ruby/object:Gem::Requirement | ||
21 | + requirements: | ||
22 | + - - ">=" | ||
23 | + - !ruby/object:Gem::Version | ||
24 | + version: 0.9.5 | ||
25 | + version: | ||
26 | +description: FakeWeb is a helper for faking web requests in Ruby. It works at a global level, without modifying code or writing extensive stubs. | ||
27 | +email: | ||
28 | +- chris@kampers.net | ||
29 | +- romeda@gmail.com | ||
30 | +executables: [] | ||
31 | + | ||
32 | +extensions: [] | ||
33 | + | ||
34 | +extra_rdoc_files: | ||
35 | +- CHANGELOG | ||
36 | +- LICENSE.txt | ||
37 | +- README.rdoc | ||
38 | +files: | ||
39 | +- CHANGELOG | ||
40 | +- LICENSE.txt | ||
41 | +- README.rdoc | ||
42 | +- Rakefile | ||
43 | +- lib/fake_web.rb | ||
44 | +- lib/fake_web/ext/net_http.rb | ||
45 | +- lib/fake_web/registry.rb | ||
46 | +- lib/fake_web/responder.rb | ||
47 | +- lib/fake_web/response.rb | ||
48 | +- lib/fake_web/stub_socket.rb | ||
49 | +- lib/fake_web/utility.rb | ||
50 | +- lib/fakeweb.rb | ||
51 | +- test/fixtures/google_response_from_curl | ||
52 | +- test/fixtures/google_response_with_transfer_encoding | ||
53 | +- test/fixtures/google_response_without_transfer_encoding | ||
54 | +- test/fixtures/test_example.txt | ||
55 | +- test/fixtures/test_txt_file | ||
56 | +- test/test_allow_net_connect.rb | ||
57 | +- test/test_deprecations.rb | ||
58 | +- test/test_fake_authentication.rb | ||
59 | +- test/test_fake_web.rb | ||
60 | +- test/test_fake_web_open_uri.rb | ||
61 | +- test/test_helper.rb | ||
62 | +- test/test_missing_open_uri.rb | ||
63 | +- test/test_precedence.rb | ||
64 | +- test/test_query_string.rb | ||
65 | +- test/test_regexes.rb | ||
66 | +- test/test_response_headers.rb | ||
67 | +- test/test_trailing_slashes.rb | ||
68 | +- test/test_utility.rb | ||
69 | +has_rdoc: true | ||
70 | +homepage: http://github.com/chrisk/fakeweb | ||
71 | +licenses: [] | ||
72 | + | ||
73 | +post_install_message: | ||
74 | +rdoc_options: | ||
75 | +- --main | ||
76 | +- README.rdoc | ||
77 | +- --title | ||
78 | +- FakeWeb API Documentation | ||
79 | +- --charset | ||
80 | +- utf-8 | ||
81 | +- --line-numbers | ||
82 | +- --inline-source | ||
83 | +require_paths: | ||
84 | +- lib | ||
85 | +required_ruby_version: !ruby/object:Gem::Requirement | ||
86 | + requirements: | ||
87 | + - - ">=" | ||
88 | + - !ruby/object:Gem::Version | ||
89 | + version: "0" | ||
90 | + version: | ||
91 | +required_rubygems_version: !ruby/object:Gem::Requirement | ||
92 | + requirements: | ||
93 | + - - ">=" | ||
94 | + - !ruby/object:Gem::Version | ||
95 | + version: "0" | ||
96 | + version: | ||
97 | +requirements: [] | ||
98 | + | ||
99 | +rubyforge_project: fakeweb | ||
100 | +rubygems_version: 1.3.4 | ||
101 | +signing_key: | ||
102 | +specification_version: 3 | ||
103 | +summary: A tool for faking responses to HTTP requests | ||
104 | +test_files: | ||
105 | +- test/fixtures/google_response_from_curl | ||
106 | +- test/fixtures/google_response_with_transfer_encoding | ||
107 | +- test/fixtures/google_response_without_transfer_encoding | ||
108 | +- test/fixtures/test_example.txt | ||
109 | +- test/fixtures/test_txt_file | ||
110 | +- test/test_allow_net_connect.rb | ||
111 | +- test/test_deprecations.rb | ||
112 | +- test/test_fake_authentication.rb | ||
113 | +- test/test_fake_web.rb | ||
114 | +- test/test_fake_web_open_uri.rb | ||
115 | +- test/test_helper.rb | ||
116 | +- test/test_missing_open_uri.rb | ||
117 | +- test/test_precedence.rb | ||
118 | +- test/test_query_string.rb | ||
119 | +- test/test_regexes.rb | ||
120 | +- test/test_response_headers.rb | ||
121 | +- test/test_trailing_slashes.rb | ||
122 | +- test/test_utility.rb |
@@ -0,0 +1,163 @@ | @@ -0,0 +1,163 @@ | ||
1 | +fakeweb (1.2.5) | ||
2 | + | ||
3 | +* fix handling of userinfo strings that contain percent-encoded unsafe | ||
4 | + characters [Chris Kampmeier, Ken Mayer] | ||
5 | + | ||
6 | +* fix that exact matches against strings/URIs with the :any method had a lower | ||
7 | + precedence than regex matches using a real HTTP method (exact matches now | ||
8 | + always take precedence) [Chris Kampmeier] | ||
9 | + | ||
10 | +* change request handling to raise an exception when more than one registered | ||
11 | + regex matches a request URI [Chris Kampmeier] | ||
12 | + | ||
13 | + | ||
14 | +fakeweb (1.2.4) | ||
15 | + | ||
16 | +* add experimental support for matching URIs via regular expressions | ||
17 | + [Jacqui Maher, Tiago Albineli Motta, Peter Wagene] | ||
18 | + | ||
19 | +* fix an exception when registering with the :response option and a string that | ||
20 | + is the same as the name of a directory in the current path [Chris Kampmeier] | ||
21 | + | ||
22 | +* DEPRECATION: Calling FakeWeb.register_uri with a :string or :file option is | ||
23 | + now deprecated. Both options have been replaced with a unified :body option, | ||
24 | + since they supply the response body (as opposed to :response, which supplies | ||
25 | + the full response including headers) [Chris Kampmeier] | ||
26 | + | ||
27 | +* add support for specifying HTTP headers as options to FakeWeb.register_uri | ||
28 | + when using the :string or :file response types, since those methods only | ||
29 | + specify a response body [David Michael, Chris Kampmeier] | ||
30 | + | ||
31 | +* DEPRECATION: Calling FakeWeb.register_uri and FakeWeb.registered_uri? without | ||
32 | + an HTTP method as the first argument is now deprecated. To match against any | ||
33 | + HTTP method (the pre-1.2.0 behavior), use :any [Chris Kampmeier] | ||
34 | + | ||
35 | + | ||
36 | +fakeweb (1.2.3) | ||
37 | + | ||
38 | +* fix the #http_version of :file and :string responses, which was returning the | ||
39 | + request URI instead of something sensible like "1.0" [Chris Kampmeier] | ||
40 | + | ||
41 | +* add method aliases in the Net::HTTP patch to eliminate warnings when running | ||
42 | + with -w [Joshua Clingenpeel] | ||
43 | + | ||
44 | +* fix that removing the redefinition of OpenURI::HTTPError in 1.2.0 caused | ||
45 | + :exception responses to raise when OpenURI isn't available [Chris Kampmeier] | ||
46 | + | ||
47 | +* fix registering an :exception response with classes that require arguments for | ||
48 | + instantiation, like Interrupt's subclasses [Chris Kampmeier] | ||
49 | + | ||
50 | + | ||
51 | +fakeweb (1.2.2) | ||
52 | + | ||
53 | +* fix that HTTP Digest and OAuth requests could raise URI::InvalidURIErrors | ||
54 | + [Bill Kocik, Chris Kampmeier] | ||
55 | + | ||
56 | + | ||
57 | +fakeweb (1.2.1) | ||
58 | + | ||
59 | +* fix that query parameters are handled correctly when registering with a URI | ||
60 | + object [Anselmo Alves, Chris Kampmeier] | ||
61 | + | ||
62 | +* fix an exception when registering with the :response option and a string | ||
63 | + containing "\0" [Jonathan Baudanza, Chris Kampmeier] | ||
64 | + | ||
65 | +* fix that trailing slashes were considered significant for requests to the root | ||
66 | + of a domain [Chris Kampmeier] | ||
67 | + | ||
68 | +* add support for HTTP basic authentication via userinfo strings in URIs | ||
69 | + [Michael Bleigh] | ||
70 | + | ||
71 | + | ||
72 | +fakeweb (1.2.0) | ||
73 | + | ||
74 | +* add lib/fakeweb.rb so you can require "fakeweb" as well [Chris Kampmeier] | ||
75 | + | ||
76 | +* fix compatibility with Ruby 1.9.1 [Chris Kampmeier] | ||
77 | + | ||
78 | +* fix that newlines in file-based responses could be doubled in the response | ||
79 | + object's body [Mark Menard, Chris Kampmeier] | ||
80 | + | ||
81 | +* fix unnecessary munging of the transfer-encoding header, which improves | ||
82 | + compatibility with mechanize [Mark Menard] | ||
83 | + | ||
84 | +* fix a test and the RCov dependency to be compatible with JRuby [Mark Menard] | ||
85 | + | ||
86 | +* remove an unnecessary redefinition of OpenURI::HTTPError [Josh Nichols] | ||
87 | + | ||
88 | +* rearrange implementation code into separate files, one per class [Josh Nichols] | ||
89 | + | ||
90 | +* fix a bug where FakeWeb.response_for would raise if the request wasn't | ||
91 | + registered [Chris Kampmeier] | ||
92 | + | ||
93 | +* add HTTP method support, so FakeWeb takes both the URI and method into | ||
94 | + account for registration, requests, and responses. Backwards-compatible with | ||
95 | + the old method signatures, which didn't have a method param. [Chris Kampmeier] | ||
96 | + | ||
97 | +* start work on Ruby 1.9 compatibility [Chris Kampmeier] | ||
98 | + | ||
99 | +* add FakeWeb.allow_net_connect= to enable/disable the pass-through to | ||
100 | + Net::HTTP for unregistered URIs [Mislav Marohnić, Chris Kampmeier] | ||
101 | + | ||
102 | +* remove setup.rb, since most people use RubyGems [Mislav Marohnić] | ||
103 | + | ||
104 | +* fix that 'http://example.com/?' (empty query) matches a registered | ||
105 | + 'http://example.com/', and vice-versa [Mislav Marohnić] | ||
106 | + | ||
107 | +* improve the test suite to not rely on an internet connection [Chris Kampmeier] | ||
108 | + | ||
109 | +* use `rake test` instead of `rake tests` [Josh Nichols] | ||
110 | + | ||
111 | +* fix an incompatibility with Ruby 1.8.6 p36 where you'd get "Errno::EINTR: | ||
112 | + Interrupted system call" exceptions in Socket#sysread for any non-faked | ||
113 | + request [Chris Kampmeier] | ||
114 | + | ||
115 | +* response rotation: you can now optionally call FakeWeb.register_uri with an | ||
116 | + array of options hashes; these are used, in order, to respond to | ||
117 | + repeated requests (to repeat a response more than once before rotating, use | ||
118 | + the :times option). Once you run out of responses, further requests always | ||
119 | + receive the last response. [Michael Shapiro] | ||
120 | + | ||
121 | +* add support for Net::HTTP's undocumented full-URI request style (fixes | ||
122 | + URI::InvalidURIErrors that you might see in older libraries) [Chris Kampmeier] | ||
123 | + | ||
124 | +* sort query params before storing internally, so that | ||
125 | + http://example.com/?a=1&b=2 and http://example.com/?b=2&a=1 are considered the | ||
126 | + same URL (although this is technically incorrect, it's much more | ||
127 | + convenient--most web apps work that way, and Net::HTTP's use of a hash to pass | ||
128 | + query params means that the order in which FakeWeb stores them can be | ||
129 | + unpredictable) [Chris Kampmeier] | ||
130 | + | ||
131 | +* add support for ports in URLs, so that http://example.com/ and | ||
132 | + http://example.com:3000/ are not the same [Chris Kampmeier] | ||
133 | + | ||
134 | +* fix for non-faked SSL requests failing with "Unable to create local socket" | ||
135 | + [Chris Kampmeier] | ||
136 | + | ||
137 | +* update Rakefile to fix warning about deprecated code [Chris Kampmeier] | ||
138 | + | ||
139 | + | ||
140 | +fakeweb (1.1.2) | ||
141 | + | ||
142 | +* add required dependencies to GemSpec to ensure that tests pass in firebrigade | ||
143 | + (http://firebrigade.seattlerb.org/) [Blaine Cook] | ||
144 | + | ||
145 | + | ||
146 | +fakeweb (1.1.1) | ||
147 | + | ||
148 | +* fix for non-existence of :string method on File as presented by open-uri | ||
149 | + [Blaine Cook] | ||
150 | + | ||
151 | +* fix for curl example test - google redirects to ccTLDs for those outside US | ||
152 | + [Blaine Cook] | ||
153 | + | ||
154 | + | ||
155 | +fakeweb (1.1.0) | ||
156 | + | ||
157 | +* update code to correspond to ruby 1.8.4 (breaks compatibility with ruby 1.8.2) | ||
158 | + [Blaine Cook] | ||
159 | + | ||
160 | + | ||
161 | +fakeweb (1.0.0) | ||
162 | + | ||
163 | + * initial import [Blaine Cook] |
@@ -0,0 +1,281 @@ | @@ -0,0 +1,281 @@ | ||
1 | + GNU GENERAL PUBLIC LICENSE | ||
2 | + Version 2, June 1991 | ||
3 | + | ||
4 | + Copyright (C) 1989, 1991 Free Software Foundation, Inc. | ||
5 | + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
6 | + Everyone is permitted to copy and distribute verbatim copies | ||
7 | + of this license document, but changing it is not allowed. | ||
8 | + | ||
9 | + Preamble | ||
10 | + | ||
11 | + The licenses for most software are designed to take away your | ||
12 | +freedom to share and change it. By contrast, the GNU General Public | ||
13 | +License is intended to guarantee your freedom to share and change free | ||
14 | +software--to make sure the software is free for all its users. This | ||
15 | +General Public License applies to most of the Free Software | ||
16 | +Foundation's software and to any other program whose authors commit to | ||
17 | +using it. (Some other Free Software Foundation software is covered by | ||
18 | +the GNU Lesser General Public License instead.) You can apply it to | ||
19 | +your programs, too. | ||
20 | + | ||
21 | + When we speak of free software, we are referring to freedom, not | ||
22 | +price. Our General Public Licenses are designed to make sure that you | ||
23 | +have the freedom to distribute copies of free software (and charge for | ||
24 | +this service if you wish), that you receive source code or can get it | ||
25 | +if you want it, that you can change the software or use pieces of it | ||
26 | +in new free programs; and that you know you can do these things. | ||
27 | + | ||
28 | + To protect your rights, we need to make restrictions that forbid | ||
29 | +anyone to deny you these rights or to ask you to surrender the rights. | ||
30 | +These restrictions translate to certain responsibilities for you if you | ||
31 | +distribute copies of the software, or if you modify it. | ||
32 | + | ||
33 | + For example, if you distribute copies of such a program, whether | ||
34 | +gratis or for a fee, you must give the recipients all the rights that | ||
35 | +you have. You must make sure that they, too, receive or can get the | ||
36 | +source code. And you must show them these terms so they know their | ||
37 | +rights. | ||
38 | + | ||
39 | + We protect your rights with two steps: (1) copyright the software, and | ||
40 | +(2) offer you this license which gives you legal permission to copy, | ||
41 | +distribute and/or modify the software. | ||
42 | + | ||
43 | + Also, for each author's protection and ours, we want to make certain | ||
44 | +that everyone understands that there is no warranty for this free | ||
45 | +software. If the software is modified by someone else and passed on, we | ||
46 | +want its recipients to know that what they have is not the original, so | ||
47 | +that any problems introduced by others will not reflect on the original | ||
48 | +authors' reputations. | ||
49 | + | ||
50 | + Finally, any free program is threatened constantly by software | ||
51 | +patents. We wish to avoid the danger that redistributors of a free | ||
52 | +program will individually obtain patent licenses, in effect making the | ||
53 | +program proprietary. To prevent this, we have made it clear that any | ||
54 | +patent must be licensed for everyone's free use or not licensed at all. | ||
55 | + | ||
56 | + The precise terms and conditions for copying, distribution and | ||
57 | +modification follow. | ||
58 | + | ||
59 | + GNU GENERAL PUBLIC LICENSE | ||
60 | + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | ||
61 | + | ||
62 | + 0. This License applies to any program or other work which contains | ||
63 | +a notice placed by the copyright holder saying it may be distributed | ||
64 | +under the terms of this General Public License. The "Program", below, | ||
65 | +refers to any such program or work, and a "work based on the Program" | ||
66 | +means either the Program or any derivative work under copyright law: | ||
67 | +that is to say, a work containing the Program or a portion of it, | ||
68 | +either verbatim or with modifications and/or translated into another | ||
69 | +language. (Hereinafter, translation is included without limitation in | ||
70 | +the term "modification".) Each licensee is addressed as "you". | ||
71 | + | ||
72 | +Activities other than copying, distribution and modification are not | ||
73 | +covered by this License; they are outside its scope. The act of | ||
74 | +running the Program is not restricted, and the output from the Program | ||
75 | +is covered only if its contents constitute a work based on the | ||
76 | +Program (independent of having been made by running the Program). | ||
77 | +Whether that is true depends on what the Program does. | ||
78 | + | ||
79 | + 1. You may copy and distribute verbatim copies of the Program's | ||
80 | +source code as you receive it, in any medium, provided that you | ||
81 | +conspicuously and appropriately publish on each copy an appropriate | ||
82 | +copyright notice and disclaimer of warranty; keep intact all the | ||
83 | +notices that refer to this License and to the absence of any warranty; | ||
84 | +and give any other recipients of the Program a copy of this License | ||
85 | +along with the Program. | ||
86 | + | ||
87 | +You may charge a fee for the physical act of transferring a copy, and | ||
88 | +you may at your option offer warranty protection in exchange for a fee. | ||
89 | + | ||
90 | + 2. You may modify your copy or copies of the Program or any portion | ||
91 | +of it, thus forming a work based on the Program, and copy and | ||
92 | +distribute such modifications or work under the terms of Section 1 | ||
93 | +above, provided that you also meet all of these conditions: | ||
94 | + | ||
95 | + a) You must cause the modified files to carry prominent notices | ||
96 | + stating that you changed the files and the date of any change. | ||
97 | + | ||
98 | + b) You must cause any work that you distribute or publish, that in | ||
99 | + whole or in part contains or is derived from the Program or any | ||
100 | + part thereof, to be licensed as a whole at no charge to all third | ||
101 | + parties under the terms of this License. | ||
102 | + | ||
103 | + c) If the modified program normally reads commands interactively | ||
104 | + when run, you must cause it, when started running for such | ||
105 | + interactive use in the most ordinary way, to print or display an | ||
106 | + announcement including an appropriate copyright notice and a | ||
107 | + notice that there is no warranty (or else, saying that you provide | ||
108 | + a warranty) and that users may redistribute the program under | ||
109 | + these conditions, and telling the user how to view a copy of this | ||
110 | + License. (Exception: if the Program itself is interactive but | ||
111 | + does not normally print such an announcement, your work based on | ||
112 | + the Program is not required to print an announcement.) | ||
113 | + | ||
114 | +These requirements apply to the modified work as a whole. If | ||
115 | +identifiable sections of that work are not derived from the Program, | ||
116 | +and can be reasonably considered independent and separate works in | ||
117 | +themselves, then this License, and its terms, do not apply to those | ||
118 | +sections when you distribute them as separate works. But when you | ||
119 | +distribute the same sections as part of a whole which is a work based | ||
120 | +on the Program, the distribution of the whole must be on the terms of | ||
121 | +this License, whose permissions for other licensees extend to the | ||
122 | +entire whole, and thus to each and every part regardless of who wrote it. | ||
123 | + | ||
124 | +Thus, it is not the intent of this section to claim rights or contest | ||
125 | +your rights to work written entirely by you; rather, the intent is to | ||
126 | +exercise the right to control the distribution of derivative or | ||
127 | +collective works based on the Program. | ||
128 | + | ||
129 | +In addition, mere aggregation of another work not based on the Program | ||
130 | +with the Program (or with a work based on the Program) on a volume of | ||
131 | +a storage or distribution medium does not bring the other work under | ||
132 | +the scope of this License. | ||
133 | + | ||
134 | + 3. You may copy and distribute the Program (or a work based on it, | ||
135 | +under Section 2) in object code or executable form under the terms of | ||
136 | +Sections 1 and 2 above provided that you also do one of the following: | ||
137 | + | ||
138 | + a) Accompany it with the complete corresponding machine-readable | ||
139 | + source code, which must be distributed under the terms of Sections | ||
140 | + 1 and 2 above on a medium customarily used for software interchange; or, | ||
141 | + | ||
142 | + b) Accompany it with a written offer, valid for at least three | ||
143 | + years, to give any third party, for a charge no more than your | ||
144 | + cost of physically performing source distribution, a complete | ||
145 | + machine-readable copy of the corresponding source code, to be | ||
146 | + distributed under the terms of Sections 1 and 2 above on a medium | ||
147 | + customarily used for software interchange; or, | ||
148 | + | ||
149 | + c) Accompany it with the information you received as to the offer | ||
150 | + to distribute corresponding source code. (This alternative is | ||
151 | + allowed only for noncommercial distribution and only if you | ||
152 | + received the program in object code or executable form with such | ||
153 | + an offer, in accord with Subsection b above.) | ||
154 | + | ||
155 | +The source code for a work means the preferred form of the work for | ||
156 | +making modifications to it. For an executable work, complete source | ||
157 | +code means all the source code for all modules it contains, plus any | ||
158 | +associated interface definition files, plus the scripts used to | ||
159 | +control compilation and installation of the executable. However, as a | ||
160 | +special exception, the source code distributed need not include | ||
161 | +anything that is normally distributed (in either source or binary | ||
162 | +form) with the major components (compiler, kernel, and so on) of the | ||
163 | +operating system on which the executable runs, unless that component | ||
164 | +itself accompanies the executable. | ||
165 | + | ||
166 | +If distribution of executable or object code is made by offering | ||
167 | +access to copy from a designated place, then offering equivalent | ||
168 | +access to copy the source code from the same place counts as | ||
169 | +distribution of the source code, even though third parties are not | ||
170 | +compelled to copy the source along with the object code. | ||
171 | + | ||
172 | + 4. You may not copy, modify, sublicense, or distribute the Program | ||
173 | +except as expressly provided under this License. Any attempt | ||
174 | +otherwise to copy, modify, sublicense or distribute the Program is | ||
175 | +void, and will automatically terminate your rights under this License. | ||
176 | +However, parties who have received copies, or rights, from you under | ||
177 | +this License will not have their licenses terminated so long as such | ||
178 | +parties remain in full compliance. | ||
179 | + | ||
180 | + 5. You are not required to accept this License, since you have not | ||
181 | +signed it. However, nothing else grants you permission to modify or | ||
182 | +distribute the Program or its derivative works. These actions are | ||
183 | +prohibited by law if you do not accept this License. Therefore, by | ||
184 | +modifying or distributing the Program (or any work based on the | ||
185 | +Program), you indicate your acceptance of this License to do so, and | ||
186 | +all its terms and conditions for copying, distributing or modifying | ||
187 | +the Program or works based on it. | ||
188 | + | ||
189 | + 6. Each time you redistribute the Program (or any work based on the | ||
190 | +Program), the recipient automatically receives a license from the | ||
191 | +original licensor to copy, distribute or modify the Program subject to | ||
192 | +these terms and conditions. You may not impose any further | ||
193 | +restrictions on the recipients' exercise of the rights granted herein. | ||
194 | +You are not responsible for enforcing compliance by third parties to | ||
195 | +this License. | ||
196 | + | ||
197 | + 7. If, as a consequence of a court judgment or allegation of patent | ||
198 | +infringement or for any other reason (not limited to patent issues), | ||
199 | +conditions are imposed on you (whether by court order, agreement or | ||
200 | +otherwise) that contradict the conditions of this License, they do not | ||
201 | +excuse you from the conditions of this License. If you cannot | ||
202 | +distribute so as to satisfy simultaneously your obligations under this | ||
203 | +License and any other pertinent obligations, then as a consequence you | ||
204 | +may not distribute the Program at all. For example, if a patent | ||
205 | +license would not permit royalty-free redistribution of the Program by | ||
206 | +all those who receive copies directly or indirectly through you, then | ||
207 | +the only way you could satisfy both it and this License would be to | ||
208 | +refrain entirely from distribution of the Program. | ||
209 | + | ||
210 | +If any portion of this section is held invalid or unenforceable under | ||
211 | +any particular circumstance, the balance of the section is intended to | ||
212 | +apply and the section as a whole is intended to apply in other | ||
213 | +circumstances. | ||
214 | + | ||
215 | +It is not the purpose of this section to induce you to infringe any | ||
216 | +patents or other property right claims or to contest validity of any | ||
217 | +such claims; this section has the sole purpose of protecting the | ||
218 | +integrity of the free software distribution system, which is | ||
219 | +implemented by public license practices. Many people have made | ||
220 | +generous contributions to the wide range of software distributed | ||
221 | +through that system in reliance on consistent application of that | ||
222 | +system; it is up to the author/donor to decide if he or she is willing | ||
223 | +to distribute software through any other system and a licensee cannot | ||
224 | +impose that choice. | ||
225 | + | ||
226 | +This section is intended to make thoroughly clear what is believed to | ||
227 | +be a consequence of the rest of this License. | ||
228 | + | ||
229 | + 8. If the distribution and/or use of the Program is restricted in | ||
230 | +certain countries either by patents or by copyrighted interfaces, the | ||
231 | +original copyright holder who places the Program under this License | ||
232 | +may add an explicit geographical distribution limitation excluding | ||
233 | +those countries, so that distribution is permitted only in or among | ||
234 | +countries not thus excluded. In such case, this License incorporates | ||
235 | +the limitation as if written in the body of this License. | ||
236 | + | ||
237 | + 9. The Free Software Foundation may publish revised and/or new versions | ||
238 | +of the General Public License from time to time. Such new versions will | ||
239 | +be similar in spirit to the present version, but may differ in detail to | ||
240 | +address new problems or concerns. | ||
241 | + | ||
242 | +Each version is given a distinguishing version number. If the Program | ||
243 | +specifies a version number of this License which applies to it and "any | ||
244 | +later version", you have the option of following the terms and conditions | ||
245 | +either of that version or of any later version published by the Free | ||
246 | +Software Foundation. If the Program does not specify a version number of | ||
247 | +this License, you may choose any version ever published by the Free Software | ||
248 | +Foundation. | ||
249 | + | ||
250 | + 10. If you wish to incorporate parts of the Program into other free | ||
251 | +programs whose distribution conditions are different, write to the author | ||
252 | +to ask for permission. For software which is copyrighted by the Free | ||
253 | +Software Foundation, write to the Free Software Foundation; we sometimes | ||
254 | +make exceptions for this. Our decision will be guided by the two goals | ||
255 | +of preserving the free status of all derivatives of our free software and | ||
256 | +of promoting the sharing and reuse of software generally. | ||
257 | + | ||
258 | + NO WARRANTY | ||
259 | + | ||
260 | + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY | ||
261 | +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN | ||
262 | +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES | ||
263 | +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED | ||
264 | +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
265 | +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS | ||
266 | +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE | ||
267 | +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, | ||
268 | +REPAIR OR CORRECTION. | ||
269 | + | ||
270 | + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | ||
271 | +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR | ||
272 | +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, | ||
273 | +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING | ||
274 | +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED | ||
275 | +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY | ||
276 | +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER | ||
277 | +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE | ||
278 | +POSSIBILITY OF SUCH DAMAGES. | ||
279 | + | ||
280 | + END OF TERMS AND CONDITIONS | ||
281 | + |
@@ -0,0 +1,193 @@ | @@ -0,0 +1,193 @@ | ||
1 | += FakeWeb | ||
2 | + | ||
3 | +FakeWeb is a helper for faking web requests in Ruby. It works at a global | ||
4 | +level, without modifying code or writing extensive stubs. | ||
5 | + | ||
6 | + | ||
7 | +== Installation | ||
8 | + | ||
9 | +The latest release of FakeWeb is once again available from your friendly | ||
10 | +RubyForge mirror. Just install the gem: | ||
11 | + | ||
12 | + sudo gem install fakeweb | ||
13 | + | ||
14 | +Note: the gem was previously available as +FakeWeb+ (capital letters), but now | ||
15 | +all versions are simply registered as +fakeweb+. If you have any old +FakeWeb+ | ||
16 | +gems lying around, remove them: <tt>sudo gem uninstall FakeWeb</tt> | ||
17 | + | ||
18 | + | ||
19 | +== Help and discussion | ||
20 | + | ||
21 | +RDocs for the current release are available at http://fakeweb.rubyforge.org. | ||
22 | + | ||
23 | +There's a mailing list for questions and discussion at | ||
24 | +http://groups.google.com/group/fakeweb-users. | ||
25 | + | ||
26 | +The main source repository is http://github.com/chrisk/fakeweb. | ||
27 | + | ||
28 | +== Examples | ||
29 | + | ||
30 | +Start by requiring FakeWeb: | ||
31 | + | ||
32 | + require 'rubygems' | ||
33 | + require 'fakeweb' | ||
34 | + | ||
35 | +=== Registering basic string responses | ||
36 | + | ||
37 | + FakeWeb.register_uri(:get, "http://example.com/test1", :body => "Hello World!") | ||
38 | + | ||
39 | + Net::HTTP.get(URI.parse("http://example.com/test1")) | ||
40 | + => "Hello World!" | ||
41 | + | ||
42 | + Net::HTTP.get(URI.parse("http://example.com/test2")) | ||
43 | + => FakeWeb is bypassed and the response from a real request is returned | ||
44 | + | ||
45 | +You can also call <tt>register_uri</tt> with a regular expression, to match | ||
46 | +more than one URI. | ||
47 | + | ||
48 | +=== Replaying a recorded response | ||
49 | + | ||
50 | + page = `curl -is http://www.google.com/` | ||
51 | + FakeWeb.register_uri(:get, "http://www.google.com/", :response => page) | ||
52 | + | ||
53 | + Net::HTTP.get(URI.parse("http://www.google.com/")) | ||
54 | + # => Full response, including headers | ||
55 | + | ||
56 | +=== Adding a custom status to the response | ||
57 | + | ||
58 | + FakeWeb.register_uri(:get, "http://example.com/", :body => "Nothing to be found 'round here", | ||
59 | + :status => ["404", "Not Found"]) | ||
60 | + | ||
61 | + Net::HTTP.start("example.com") do |req| | ||
62 | + response = req.get("/") | ||
63 | + response.code # => "404" | ||
64 | + response.message # => "Not Found" | ||
65 | + response.body # => "Nothing to be found 'round here" | ||
66 | + end | ||
67 | + | ||
68 | +=== Responding to any HTTP method | ||
69 | + | ||
70 | + FakeWeb.register_uri(:any, "http://example.com", :body => "response for any HTTP method") | ||
71 | + | ||
72 | +If you use the <tt>:any</tt> symbol, the URI you specify will be completely | ||
73 | +stubbed out (regardless of the HTTP method of the request). This can be useful | ||
74 | +for RPC-like services, where the HTTP method isn't significant. (Older | ||
75 | +versions of FakeWeb always behaved like this, and didn't accept the first | ||
76 | ++method+ argument above; this syntax is now deprecated.) | ||
77 | + | ||
78 | +=== Rotating responses | ||
79 | + | ||
80 | +You can optionally call FakeWeb.register_uri with an array of options hashes; | ||
81 | +these are used, in order, to respond to repeated requests. Once you run out of | ||
82 | +responses, further requests always receive the last response. (You can also send | ||
83 | +a response more than once before rotating, by specifying a <tt>:times</tt> | ||
84 | +option for that response.) | ||
85 | + | ||
86 | + FakeWeb.register_uri(:delete, "http://example.com/posts/1", | ||
87 | + [{:body => "Post 1 deleted.", :status => ["200", "OK"]}, | ||
88 | + {:body => "Post not found", :status => ["404", "Not Found"]}]) | ||
89 | + | ||
90 | + Net::HTTP.start("example.com") do |req| | ||
91 | + req.delete("/posts/1").body # => "Post 1 deleted" | ||
92 | + req.delete("/posts/1").body # => "Post not found" | ||
93 | + req.delete("/posts/1").body # => "Post not found" | ||
94 | + end | ||
95 | + | ||
96 | +=== Using HTTP basic authentication | ||
97 | + | ||
98 | +You can stub requests that use basic authentication with +userinfo+ strings in | ||
99 | +the URIs: | ||
100 | + | ||
101 | + FakeWeb.register_uri(:get, "http://example.com/secret", :body => "Unauthorized", :status => ["401", "Unauthorized"]) | ||
102 | + FakeWeb.register_uri(:get, "http://user:pass@example.com/secret", :body => "Authorized") | ||
103 | + | ||
104 | + Net::HTTP.start("example.com") do |http| | ||
105 | + req = Net::HTTP::Get.new("/secret") | ||
106 | + http.request(req) # => "Unauthorized" | ||
107 | + req.basic_auth("user", "pass") | ||
108 | + http.request(req) # => "Authorized" | ||
109 | + end | ||
110 | + | ||
111 | +=== Clearing registered URIs | ||
112 | + | ||
113 | +The FakeWeb registry is a singleton that lasts for the duration of your | ||
114 | +program, maintaining every fake response you register. If needed, you | ||
115 | +can clean out the registry and remove all registered URIs: | ||
116 | + | ||
117 | + FakeWeb.clean_registry | ||
118 | + | ||
119 | +=== Blocking all real requests | ||
120 | + | ||
121 | +When you're using FakeWeb to replace _all_ of your requests, it's useful to | ||
122 | +catch when requests are made for unregistered URIs (unlike the default | ||
123 | +behavior, which is to pass those requests through to Net::HTTP as usual). | ||
124 | + | ||
125 | + FakeWeb.allow_net_connect = false | ||
126 | + Net::HTTP.get(URI.parse("http://example.com/")) | ||
127 | + => raises FakeWeb::NetConnectNotAllowedError | ||
128 | + | ||
129 | + FakeWeb.allow_net_connect = true | ||
130 | + Net::HTTP.get(URI.parse("http://example.com/")) | ||
131 | + => FakeWeb is bypassed and the response from a real request is returned | ||
132 | + | ||
133 | +This is handy when you want to make sure your tests are self-contained, or you | ||
134 | +want to catch the scenario when a URI is changed in implementation code | ||
135 | +without a corresponding test change. | ||
136 | + | ||
137 | +=== Specifying HTTP response headers | ||
138 | + | ||
139 | +When you register a response using the <tt>:body</tt> option, you're only | ||
140 | +setting the body of the response. If you want to add headers to these responses, | ||
141 | +simply add the header as an option to +register_uri+: | ||
142 | + | ||
143 | + FakeWeb.register_uri(:get, "http://example.com/hello.txt", :body => "Hello", :content_type => "text/plain") | ||
144 | + | ||
145 | +This sets the "Content-Type" header in the response. | ||
146 | + | ||
147 | +== More info | ||
148 | + | ||
149 | +FakeWeb lets you decouple your test environment from live services without | ||
150 | +modifying code or writing extensive stubs. | ||
151 | + | ||
152 | +In addition to the conceptual advantage of having idempotent request | ||
153 | +behaviour, FakeWeb makes tests run faster than if they were made to remote (or | ||
154 | +even local) web servers. It also makes it possible to run tests without a | ||
155 | +network connection or in situations where the server is behind a firewall or | ||
156 | +has host-based access controls. | ||
157 | + | ||
158 | +FakeWeb works with anything based on Net::HTTP--both higher-level wrappers, | ||
159 | +like OpenURI, as well as a ton of libraries for popular web services. | ||
160 | + | ||
161 | + | ||
162 | +== Known Issues | ||
163 | + | ||
164 | +* Request bodies are ignored, including PUT and POST parameters. If you need | ||
165 | + different responses for different request bodies, you need to request | ||
166 | + different URLs, and register different responses for each. (Query strings are | ||
167 | + fully supported, though.) We're currently considering how the API should | ||
168 | + change to add support for request bodies in 1.3.0. Your input would be really | ||
169 | + helpful: see http://groups.google.com/group/fakeweb-users/browse_thread/thread/44d190a6b12e4273 | ||
170 | + for a discussion of some different options. Thanks! | ||
171 | + | ||
172 | + | ||
173 | +== Copyright | ||
174 | + | ||
175 | +Copyright 2006-2007 Blaine Cook | ||
176 | + | ||
177 | +Copyright 2008-2009 various contributors | ||
178 | + | ||
179 | + FakeWeb is free software; you can redistribute it and/or modify it under the | ||
180 | + terms of the GNU General Public License as published by the Free Software | ||
181 | + Foundation; either version 2 of the License, or (at your option) any later | ||
182 | + version. | ||
183 | + | ||
184 | + FakeWeb is distributed in the hope that it will be useful, but WITHOUT ANY | ||
185 | + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
186 | + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | ||
187 | + details. | ||
188 | + | ||
189 | + You should have received a copy of the GNU General Public License along | ||
190 | + with FakeWeb; if not, write to the Free Software Foundation, Inc., 51 | ||
191 | + Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
192 | + | ||
193 | +See <tt>LICENSE.txt</tt> for the full terms. |
@@ -0,0 +1,76 @@ | @@ -0,0 +1,76 @@ | ||
1 | +puts "Using ruby #{RUBY_VERSION}p#{RUBY_PATCHLEVEL}" | ||
2 | + | ||
3 | +require 'rubygems' | ||
4 | +require 'rake/gempackagetask' | ||
5 | +require 'rake/testtask' | ||
6 | +begin | ||
7 | + require 'rdoc/task' | ||
8 | +rescue LoadError | ||
9 | + puts "\nIt looks like you're using an old version of RDoc, but FakeWeb requires a newer one." | ||
10 | + puts "You can try upgrading with `sudo gem install rdoc`.\n\n" | ||
11 | + raise | ||
12 | +end | ||
13 | + | ||
14 | +task :default => :test | ||
15 | + | ||
16 | +desc "Run All Tests" | ||
17 | +Rake::TestTask.new :test do |test| | ||
18 | + test.test_files = ["test/**/*.rb"] | ||
19 | + test.verbose = false | ||
20 | +end | ||
21 | + | ||
22 | +desc "Generate Documentation" | ||
23 | +RDoc::Task.new do |rdoc| | ||
24 | + rdoc.main = "README.rdoc" | ||
25 | + rdoc.rdoc_dir = "doc" | ||
26 | + rdoc.rdoc_files.include("README.rdoc", "CHANGELOG", "LICENSE.txt", "lib/*.rb") | ||
27 | + rdoc.title = "FakeWeb API Documentation" | ||
28 | + rdoc.options << '--line-numbers' << '--charset' << 'utf-8' | ||
29 | +end | ||
30 | + | ||
31 | +desc %{Update ".manifest" with the latest list of project filenames. Respect\ | ||
32 | +.gitignore by excluding everything that git ignores. Update `files` and\ | ||
33 | +`test_files` arrays in "*.gemspec" file if it's present.} | ||
34 | +task :manifest do | ||
35 | + list = Dir['**/*'].sort | ||
36 | + spec_file = Dir['*.gemspec'].first | ||
37 | + list -= [spec_file] if spec_file | ||
38 | + | ||
39 | + File.read('.gitignore').each_line do |glob| | ||
40 | + glob = glob.chomp.sub(/^\//, '') | ||
41 | + list -= Dir[glob] | ||
42 | + list -= Dir["#{glob}/**/*"] if File.directory?(glob) and !File.symlink?(glob) | ||
43 | + puts "excluding #{glob}" | ||
44 | + end | ||
45 | + | ||
46 | + if spec_file | ||
47 | + spec = File.read spec_file | ||
48 | + spec.gsub!(/^(\s* s.(test_)?files \s* = \s* )( \[ [^\]]* \] | %w\( [^)]* \) )/mx) do | ||
49 | + assignment = $1 | ||
50 | + bunch = $2 ? list.grep(/^test\//) : list | ||
51 | + '%s%%w(%s)' % [assignment, bunch.join(' ')] | ||
52 | + end | ||
53 | + | ||
54 | + File.open(spec_file, 'w') {|f| f << spec } | ||
55 | + end | ||
56 | + File.open('.manifest', 'w') {|f| f << list.join("\n") } | ||
57 | +end | ||
58 | + | ||
59 | +if RUBY_PLATFORM =~ /java/ | ||
60 | + puts "rcov support disabled (running under JRuby)." | ||
61 | +elsif RUBY_VERSION =~ /^1\.9/ | ||
62 | + puts "rcov support disabled (running under Ruby 1.9)" | ||
63 | +else | ||
64 | + require 'rcov/rcovtask' | ||
65 | + Rcov::RcovTask.new do |t| | ||
66 | + t.test_files = FileList['test/**/test*.rb'] | ||
67 | + t.rcov_opts << "--sort coverage" | ||
68 | + t.rcov_opts << "--exclude gems" | ||
69 | + end | ||
70 | +end | ||
71 | + | ||
72 | +spec = eval(File.read(File.join(File.dirname(__FILE__), "fakeweb.gemspec"))) | ||
73 | +Rake::GemPackageTask.new(spec) do |pkg| | ||
74 | + pkg.need_tar_gz = true | ||
75 | + pkg.need_zip = true | ||
76 | +end |
@@ -0,0 +1,172 @@ | @@ -0,0 +1,172 @@ | ||
1 | +require 'singleton' | ||
2 | + | ||
3 | +require 'fake_web/ext/net_http' | ||
4 | +require 'fake_web/registry' | ||
5 | +require 'fake_web/response' | ||
6 | +require 'fake_web/responder' | ||
7 | +require 'fake_web/stub_socket' | ||
8 | +require 'fake_web/utility' | ||
9 | + | ||
10 | +module FakeWeb | ||
11 | + | ||
12 | + # Resets the FakeWeb Registry. This will force all subsequent web requests to | ||
13 | + # behave as real requests. | ||
14 | + def self.clean_registry | ||
15 | + Registry.instance.clean_registry | ||
16 | + end | ||
17 | + | ||
18 | + # Enables or disables real HTTP connections for requests that don't match | ||
19 | + # registered URIs. | ||
20 | + # | ||
21 | + # If you set <tt>FakeWeb.allow_net_connect = false</tt> and subsequently try | ||
22 | + # to make a request to a URI you haven't registered with #register_uri, a | ||
23 | + # NetConnectNotAllowedError will be raised. This is handy when you want to | ||
24 | + # make sure your tests are self-contained, or want to catch the scenario | ||
25 | + # when a URI is changed in implementation code without a corresponding test | ||
26 | + # change. | ||
27 | + # | ||
28 | + # When <tt>FakeWeb.allow_net_connect = true</tt> (the default), requests to | ||
29 | + # URIs not stubbed with FakeWeb are passed through to Net::HTTP. | ||
30 | + def self.allow_net_connect=(allowed) | ||
31 | + @allow_net_connect = allowed | ||
32 | + end | ||
33 | + | ||
34 | + # Enable pass-through to Net::HTTP by default. | ||
35 | + self.allow_net_connect = true | ||
36 | + | ||
37 | + # Returns +true+ if requests to URIs not registered with FakeWeb are passed | ||
38 | + # through to Net::HTTP for normal processing (the default). Returns +false+ | ||
39 | + # if an exception is raised for these requests. | ||
40 | + def self.allow_net_connect? | ||
41 | + @allow_net_connect | ||
42 | + end | ||
43 | + | ||
44 | + # This exception is raised if you set <tt>FakeWeb.allow_net_connect = | ||
45 | + # false</tt> and subsequently try to make a request to a URI you haven't | ||
46 | + # stubbed. | ||
47 | + class NetConnectNotAllowedError < StandardError; end; | ||
48 | + | ||
49 | + # This exception is raised if a Net::HTTP request matches more than one of | ||
50 | + # the regular expression-based stubs you've registered. To fix the problem, | ||
51 | + # disambiguate the regular expressions by making them more specific. | ||
52 | + class MultipleMatchingRegexpsError < StandardError; end; | ||
53 | + | ||
54 | + # call-seq: | ||
55 | + # FakeWeb.register_uri(method, uri, options) | ||
56 | + # | ||
57 | + # Register requests using the HTTP method specified by the symbol +method+ | ||
58 | + # for +uri+ to be handled according to +options+. If you specify the method | ||
59 | + # <tt>:any</tt>, the response will be reigstered for any request for +uri+. | ||
60 | + # +uri+ can be a +String+, +URI+, or +Regexp+ object. +options+ must be either | ||
61 | + # a +Hash+ or an +Array+ of +Hashes+ (see below), which must contain one of | ||
62 | + # these two keys: | ||
63 | + # | ||
64 | + # <tt>:body</tt>:: | ||
65 | + # A string which is used as the body of the response. If the string refers | ||
66 | + # to a valid filesystem path, the contents of that file will be read and used | ||
67 | + # as the body of the response instead. (This used to be two options, | ||
68 | + # <tt>:string</tt> and <tt>:file</tt>, respectively. These are now deprecated.) | ||
69 | + # <tt>:response</tt>:: | ||
70 | + # Either an <tt>Net::HTTPResponse</tt>, an +IO+, or a +String+ which is used | ||
71 | + # as the full response for the request. | ||
72 | + # | ||
73 | + # The easier way by far is to pass the <tt>:response</tt> option to | ||
74 | + # +register_uri+ as a +String+ or an (open for reads) +IO+ object which | ||
75 | + # will be used as the complete HTTP response, including headers and body. | ||
76 | + # If the string points to a readable file, this file will be used as the | ||
77 | + # content for the request. | ||
78 | + # | ||
79 | + # To obtain a complete response document, you can use the +curl+ command, | ||
80 | + # like so: | ||
81 | + # | ||
82 | + # curl -i http://www.example.com/ > response_for_www.example.com | ||
83 | + # | ||
84 | + # which can then be used in your test environment like so: | ||
85 | + # | ||
86 | + # FakeWeb.register_uri(:get, 'http://www.example.com/', :response => 'response_for_www.example.com') | ||
87 | + # | ||
88 | + # See the <tt>Net::HTTPResponse</tt> | ||
89 | + # documentation[http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/classes/Net/HTTPResponse.html] | ||
90 | + # for more information on creating custom response objects. | ||
91 | + # | ||
92 | + # +options+ may also be an +Array+ containing a list of the above-described | ||
93 | + # +Hash+. In this case, FakeWeb will rotate through each provided response, | ||
94 | + # you may optionally provide: | ||
95 | + # | ||
96 | + # <tt>:times</tt>:: | ||
97 | + # The number of times this response will be used. Decremented by one each time it's called. | ||
98 | + # FakeWeb will use the final provided request indefinitely, regardless of its :times parameter. | ||
99 | + # | ||
100 | + # Two optional arguments are also accepted: | ||
101 | + # | ||
102 | + # <tt>:status</tt>:: | ||
103 | + # Passing <tt>:status</tt> as a two-value array will set the response code | ||
104 | + # and message. The defaults are <tt>200</tt> and <tt>OK</tt>, respectively. | ||
105 | + # Example: | ||
106 | + # FakeWeb.register_uri("http://www.example.com/", :body => "Go away!", :status => [404, "Not Found"]) | ||
107 | + # <tt>:exception</tt>:: | ||
108 | + # The argument passed via <tt>:exception</tt> will be raised when the | ||
109 | + # specified URL is requested. Any +Exception+ class is valid. Example: | ||
110 | + # FakeWeb.register_uri('http://www.example.com/', :exception => Net::HTTPError) | ||
111 | + # | ||
112 | + # If you're using the <tt>:body</tt> response type, you can pass additional | ||
113 | + # options to specify the HTTP headers to be used in the response. Example: | ||
114 | + # | ||
115 | + # FakeWeb.register_uri(:get, "http://example.com/index.txt", :body => "Hello", :content_type => "text/plain") | ||
116 | + def self.register_uri(*args) | ||
117 | + case args.length | ||
118 | + when 3 | ||
119 | + Registry.instance.register_uri(*args) | ||
120 | + when 2 | ||
121 | + print_missing_http_method_deprecation_warning(*args) | ||
122 | + Registry.instance.register_uri(:any, *args) | ||
123 | + else | ||
124 | + raise ArgumentError.new("wrong number of arguments (#{args.length} for 3)") | ||
125 | + end | ||
126 | + end | ||
127 | + | ||
128 | + # call-seq: | ||
129 | + # FakeWeb.response_for(method, uri) | ||
130 | + # | ||
131 | + # Returns the faked Net::HTTPResponse object associated with +method+ and +uri+. | ||
132 | + def self.response_for(*args, &block) #:nodoc: :yields: response | ||
133 | + case args.length | ||
134 | + when 2 | ||
135 | + Registry.instance.response_for(*args, &block) | ||
136 | + when 1 | ||
137 | + print_missing_http_method_deprecation_warning(*args) | ||
138 | + Registry.instance.response_for(:any, *args, &block) | ||
139 | + else | ||
140 | + raise ArgumentError.new("wrong number of arguments (#{args.length} for 2)") | ||
141 | + end | ||
142 | + end | ||
143 | + | ||
144 | + # call-seq: | ||
145 | + # FakeWeb.registered_uri?(method, uri) | ||
146 | + # | ||
147 | + # Returns true if a +method+ request for +uri+ is registered with FakeWeb. | ||
148 | + # Specify a method of <tt>:any</tt> to check for against all HTTP methods. | ||
149 | + def self.registered_uri?(*args) | ||
150 | + case args.length | ||
151 | + when 2 | ||
152 | + Registry.instance.registered_uri?(*args) | ||
153 | + when 1 | ||
154 | + print_missing_http_method_deprecation_warning(*args) | ||
155 | + Registry.instance.registered_uri?(:any, *args) | ||
156 | + else | ||
157 | + raise ArgumentError.new("wrong number of arguments (#{args.length} for 2)") | ||
158 | + end | ||
159 | + end | ||
160 | + | ||
161 | + private | ||
162 | + | ||
163 | + def self.print_missing_http_method_deprecation_warning(*args) | ||
164 | + method = caller.first.match(/`(.*?)'/)[1] | ||
165 | + new_args = args.map { |a| a.inspect }.unshift(":any") | ||
166 | + new_args.last.gsub!(/^\{|\}$/, "").gsub!("=>", " => ") if args.last.is_a?(Hash) | ||
167 | + $stderr.puts | ||
168 | + $stderr.puts "Deprecation warning: FakeWeb requires an HTTP method argument (or use :any). Try this:" | ||
169 | + $stderr.puts " FakeWeb.#{method}(#{new_args.join(', ')})" | ||
170 | + $stderr.puts "Called at #{caller[1]}" | ||
171 | + end | ||
172 | +end |
@@ -0,0 +1,71 @@ | @@ -0,0 +1,71 @@ | ||
1 | +require 'net/http' | ||
2 | +require 'net/https' | ||
3 | +require 'stringio' | ||
4 | + | ||
5 | +module Net #:nodoc: all | ||
6 | + | ||
7 | + class BufferedIO | ||
8 | + alias initialize_without_fakeweb initialize | ||
9 | + def initialize(io, debug_output = nil) | ||
10 | + @read_timeout = 60 | ||
11 | + @rbuf = '' | ||
12 | + @debug_output = debug_output | ||
13 | + | ||
14 | + @io = case io | ||
15 | + when Socket, OpenSSL::SSL::SSLSocket, IO | ||
16 | + io | ||
17 | + when String | ||
18 | + if !io.include?("\0") && File.exists?(io) && !File.directory?(io) | ||
19 | + File.open(io, "r") | ||
20 | + else | ||
21 | + StringIO.new(io) | ||
22 | + end | ||
23 | + end | ||
24 | + raise "Unable to create local socket" unless @io | ||
25 | + end | ||
26 | + end | ||
27 | + | ||
28 | + class HTTP | ||
29 | + class << self | ||
30 | + alias socket_type_without_fakeweb socket_type | ||
31 | + def socket_type | ||
32 | + FakeWeb::StubSocket | ||
33 | + end | ||
34 | + end | ||
35 | + | ||
36 | + alias request_without_fakeweb request | ||
37 | + def request(request, body = nil, &block) | ||
38 | + protocol = use_ssl? ? "https" : "http" | ||
39 | + | ||
40 | + path = request.path | ||
41 | + path = URI.parse(request.path).request_uri if request.path =~ /^http/ | ||
42 | + | ||
43 | + if request["authorization"] =~ /^Basic / | ||
44 | + userinfo = FakeWeb::Utility.decode_userinfo_from_header(request["authorization"]) | ||
45 | + userinfo = FakeWeb::Utility.encode_unsafe_chars_in_userinfo(userinfo) + "@" | ||
46 | + else | ||
47 | + userinfo = "" | ||
48 | + end | ||
49 | + | ||
50 | + uri = "#{protocol}://#{userinfo}#{self.address}:#{self.port}#{path}" | ||
51 | + method = request.method.downcase.to_sym | ||
52 | + | ||
53 | + if FakeWeb.registered_uri?(method, uri) | ||
54 | + @socket = Net::HTTP.socket_type.new | ||
55 | + FakeWeb.response_for(method, uri, &block) | ||
56 | + elsif FakeWeb.allow_net_connect? | ||
57 | + connect_without_fakeweb | ||
58 | + request_without_fakeweb(request, body, &block) | ||
59 | + else | ||
60 | + uri = FakeWeb::Utility.strip_default_port_from_uri(uri) | ||
61 | + raise FakeWeb::NetConnectNotAllowedError, | ||
62 | + "Real HTTP connections are disabled. Unregistered request: #{request.method} #{uri}" | ||
63 | + end | ||
64 | + end | ||
65 | + | ||
66 | + alias connect_without_fakeweb connect | ||
67 | + def connect | ||
68 | + end | ||
69 | + end | ||
70 | + | ||
71 | +end |
@@ -0,0 +1,103 @@ | @@ -0,0 +1,103 @@ | ||
1 | +module FakeWeb | ||
2 | + class Registry #:nodoc: | ||
3 | + include Singleton | ||
4 | + | ||
5 | + attr_accessor :uri_map | ||
6 | + | ||
7 | + def initialize | ||
8 | + clean_registry | ||
9 | + end | ||
10 | + | ||
11 | + def clean_registry | ||
12 | + self.uri_map = Hash.new { |hash, key| hash[key] = {} } | ||
13 | + end | ||
14 | + | ||
15 | + def register_uri(method, uri, options) | ||
16 | + uri_map[normalize_uri(uri)][method] = [*[options]].flatten.collect do |option| | ||
17 | + FakeWeb::Responder.new(method, uri, option, option[:times]) | ||
18 | + end | ||
19 | + end | ||
20 | + | ||
21 | + def registered_uri?(method, uri) | ||
22 | + normalized_uri = normalize_uri(uri) | ||
23 | + !responses_for(method, uri).empty? | ||
24 | + end | ||
25 | + | ||
26 | + def response_for(method, uri, &block) | ||
27 | + responses = responses_for(method, uri) | ||
28 | + return nil if responses.empty? | ||
29 | + | ||
30 | + next_response = responses.last | ||
31 | + responses.each do |response| | ||
32 | + if response.times and response.times > 0 | ||
33 | + response.times -= 1 | ||
34 | + next_response = response | ||
35 | + break | ||
36 | + end | ||
37 | + end | ||
38 | + | ||
39 | + next_response.response(&block) | ||
40 | + end | ||
41 | + | ||
42 | + | ||
43 | + private | ||
44 | + | ||
45 | + def responses_for(method, uri) | ||
46 | + uri = normalize_uri(uri) | ||
47 | + | ||
48 | + if uri_map[uri].has_key?(method) | ||
49 | + uri_map[uri][method] | ||
50 | + elsif uri_map[uri].has_key?(:any) | ||
51 | + uri_map[uri][:any] | ||
52 | + elsif uri_map_matches?(method, uri) | ||
53 | + uri_map_matches(method, uri) | ||
54 | + elsif uri_map_matches(:any, uri) | ||
55 | + uri_map_matches(:any, uri) | ||
56 | + else | ||
57 | + [] | ||
58 | + end | ||
59 | + end | ||
60 | + | ||
61 | + def uri_map_matches?(method, uri) | ||
62 | + !uri_map_matches(method, uri).nil? | ||
63 | + end | ||
64 | + | ||
65 | + def uri_map_matches(method, uri) | ||
66 | + uri = normalize_uri(uri.to_s).to_s | ||
67 | + uri = Utility.strip_default_port_from_uri(uri) | ||
68 | + | ||
69 | + matches = uri_map.select { |registered_uri, method_hash| | ||
70 | + registered_uri.is_a?(Regexp) && uri.match(registered_uri) && method_hash.has_key?(method) | ||
71 | + } | ||
72 | + | ||
73 | + if matches.size > 1 | ||
74 | + raise MultipleMatchingRegexpsError, | ||
75 | + "More than one regular expression matched this request: #{method.to_s.upcase} #{uri}" | ||
76 | + end | ||
77 | + | ||
78 | + matches.map { |_, method_hash| method_hash[method] }.first | ||
79 | + end | ||
80 | + | ||
81 | + def normalize_uri(uri) | ||
82 | + return uri if uri.is_a?(Regexp) | ||
83 | + normalized_uri = | ||
84 | + case uri | ||
85 | + when URI then uri | ||
86 | + when String | ||
87 | + uri = 'http://' + uri unless uri.match('^https?://') | ||
88 | + URI.parse(uri) | ||
89 | + end | ||
90 | + normalized_uri.query = sort_query_params(normalized_uri.query) | ||
91 | + normalized_uri.normalize | ||
92 | + end | ||
93 | + | ||
94 | + def sort_query_params(query) | ||
95 | + if query.nil? || query.empty? | ||
96 | + nil | ||
97 | + else | ||
98 | + query.split('&').sort.join('&') | ||
99 | + end | ||
100 | + end | ||
101 | + | ||
102 | + end | ||
103 | +end |
@@ -0,0 +1,113 @@ | @@ -0,0 +1,113 @@ | ||
1 | +module FakeWeb | ||
2 | + class Responder #:nodoc: | ||
3 | + | ||
4 | + attr_accessor :method, :uri, :options, :times | ||
5 | + KNOWN_OPTIONS = [:body, :exception, :response, :status].freeze | ||
6 | + | ||
7 | + def initialize(method, uri, options, times) | ||
8 | + self.method = method | ||
9 | + self.uri = uri | ||
10 | + self.options = options | ||
11 | + self.times = times ? times : 1 | ||
12 | + | ||
13 | + if options.has_key?(:file) || options.has_key?(:string) | ||
14 | + print_file_string_options_deprecation_warning | ||
15 | + options[:body] = options.delete(:file) || options.delete(:string) | ||
16 | + end | ||
17 | + end | ||
18 | + | ||
19 | + def response(&block) | ||
20 | + if has_baked_response? | ||
21 | + response = baked_response | ||
22 | + else | ||
23 | + code, msg = meta_information | ||
24 | + response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg) | ||
25 | + response.instance_variable_set(:@body, body) | ||
26 | + headers_extracted_from_options.each { |name, value| response[name] = value } | ||
27 | + end | ||
28 | + | ||
29 | + response.instance_variable_set(:@read, true) | ||
30 | + response.extend FakeWeb::Response | ||
31 | + | ||
32 | + optionally_raise(response) | ||
33 | + | ||
34 | + yield response if block_given? | ||
35 | + | ||
36 | + response | ||
37 | + end | ||
38 | + | ||
39 | + private | ||
40 | + | ||
41 | + def headers_extracted_from_options | ||
42 | + options.reject {|name, _| KNOWN_OPTIONS.include?(name) }.map { |name, value| | ||
43 | + [name.to_s.split("_").map { |segment| segment.capitalize }.join("-"), value] | ||
44 | + } | ||
45 | + end | ||
46 | + | ||
47 | + def body | ||
48 | + return '' unless options.has_key?(:body) | ||
49 | + | ||
50 | + if !options[:body].include?("\0") && File.exists?(options[:body]) && !File.directory?(options[:body]) | ||
51 | + File.read(options[:body]) | ||
52 | + else | ||
53 | + options[:body] | ||
54 | + end | ||
55 | + end | ||
56 | + | ||
57 | + def baked_response | ||
58 | + resp = case options[:response] | ||
59 | + when Net::HTTPResponse then options[:response] | ||
60 | + when String | ||
61 | + socket = Net::BufferedIO.new(options[:response]) | ||
62 | + r = Net::HTTPResponse.read_new(socket) | ||
63 | + | ||
64 | + # Store the oiriginal transfer-encoding | ||
65 | + saved_transfer_encoding = r.instance_eval { | ||
66 | + @header['transfer-encoding'] if @header.key?('transfer-encoding') | ||
67 | + } | ||
68 | + | ||
69 | + # read the body of response. | ||
70 | + r.instance_eval { @header['transfer-encoding'] = nil } | ||
71 | + r.reading_body(socket, true) {} | ||
72 | + | ||
73 | + # Delete the transfer-encoding key from r.@header if there wasn't one, | ||
74 | + # else restore the saved_transfer_encoding. | ||
75 | + if saved_transfer_encoding.nil? | ||
76 | + r.instance_eval { @header.delete('transfer-encoding') } | ||
77 | + else | ||
78 | + r.instance_eval { @header['transfer-encoding'] = saved_transfer_encoding } | ||
79 | + end | ||
80 | + r | ||
81 | + else raise StandardError, "Handler unimplemented for response #{options[:response]}" | ||
82 | + end | ||
83 | + end | ||
84 | + | ||
85 | + def has_baked_response? | ||
86 | + options.has_key?(:response) | ||
87 | + end | ||
88 | + | ||
89 | + def optionally_raise(response) | ||
90 | + return unless options.has_key?(:exception) | ||
91 | + | ||
92 | + case options[:exception].to_s | ||
93 | + when "Net::HTTPError", "OpenURI::HTTPError" | ||
94 | + raise options[:exception].new('Exception from FakeWeb', response) | ||
95 | + else | ||
96 | + raise options[:exception].new('Exception from FakeWeb') | ||
97 | + end | ||
98 | + end | ||
99 | + | ||
100 | + def meta_information | ||
101 | + options.has_key?(:status) ? options[:status] : [200, 'OK'] | ||
102 | + end | ||
103 | + | ||
104 | + def print_file_string_options_deprecation_warning | ||
105 | + which = options.has_key?(:file) ? :file : :string | ||
106 | + $stderr.puts | ||
107 | + $stderr.puts "Deprecation warning: FakeWeb's :#{which} option has been renamed to :body." | ||
108 | + $stderr.puts "Just replace :#{which} with :body in your FakeWeb.register_uri calls." | ||
109 | + $stderr.puts "Called at #{caller[6]}" | ||
110 | + end | ||
111 | + | ||
112 | + end | ||
113 | +end | ||
0 | \ No newline at end of file | 114 | \ No newline at end of file |
@@ -0,0 +1,22 @@ | @@ -0,0 +1,22 @@ | ||
1 | +module FakeWeb | ||
2 | + module Utility #:nodoc: | ||
3 | + | ||
4 | + def self.decode_userinfo_from_header(header) | ||
5 | + header.sub(/^Basic /, "").unpack("m").first | ||
6 | + end | ||
7 | + | ||
8 | + def self.encode_unsafe_chars_in_userinfo(userinfo) | ||
9 | + unsafe_in_userinfo = /[^#{URI::REGEXP::PATTERN::UNRESERVED};&=+$,]|^(#{URI::REGEXP::PATTERN::ESCAPED})/ | ||
10 | + userinfo.split(":").map { |part| URI.escape(part, unsafe_in_userinfo) }.join(":") | ||
11 | + end | ||
12 | + | ||
13 | + def self.strip_default_port_from_uri(uri) | ||
14 | + case uri | ||
15 | + when %r{^http://} then uri.sub(%r{:80(/|$)}, '\1') | ||
16 | + when %r{^https://} then uri.sub(%r{:443(/|$)}, '\1') | ||
17 | + else uri | ||
18 | + end | ||
19 | + end | ||
20 | + | ||
21 | + end | ||
22 | +end |
vendor/gems/fakeweb-1.2.5/test/fixtures/google_response_from_curl
0 → 100644
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +HTTP/1.1 200 OK | ||
2 | +Cache-Control: private, max-age=0 | ||
3 | +Date: Sun, 01 Feb 2009 02:16:24 GMT | ||
4 | +Expires: -1 | ||
5 | +Content-Type: text/html; charset=ISO-8859-1 | ||
6 | +Set-Cookie: PREF=ID=a6d9b5f5a4056dfe:TM=1233454584:LM=1233454584:S=U9pSwSu4eQwOPenX; expires=Tue, 01-Feb-2011 02:16:24 GMT; path=/; domain=.google.com | ||
7 | +Server: gws | ||
8 | +Transfer-Encoding: chunked | ||
9 | + | ||
10 | +<html><head><meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"><title>Google</title><script>var _gjwl=location;function _gjuc(){var a=_gjwl.hash;if(a.indexOf("&q=")>0||a.indexOf("#q=")>=0){a=a.substring(1);if(a.indexOf("#")==-1){for(var c=0;c<a.length;){var d=c;if(a.charAt(d)=="&")++d;var b=a.indexOf("&",d);if(b==-1)b=a.length;var e=a.substring(d,b);if(e.indexOf("fp=")==0){a=a.substring(0,c)+a.substring(b,a.length);b=c}else if(e=="cad=h")return 0;c=b}_gjwl.href="search?"+a+"&cad=h";return 1}}return 0}; | ||
11 | +window._gjuc && location.hash && _gjuc();</script><style>body,td,a,p,.h{font-family:arial,sans-serif}.h{color:#36c;font-size:20px}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}#gbar{height:22px;padding-left:2px}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}#gbi,#gbs{background:#fff;left:0;position:absolute;top:24px;visibility:hidden;z-index:1000}#gbi{border:1px solid;border-color:#c9d7f1 #36c #36c #a2bae7;z-index:1001}#guser{padding-bottom:7px !important}#gbar,#guser{font-size:13px;padding-top:1px !important}@media all{.gb1,.gb3{height:22px;margin-right:.73em;vertical-align:top}#gbar{float:left}}.gb2{display:block;padding:.2em .5em}a.gb1,a.gb2,a.gb3{color:#00c !important}.gb2,.gb3{text-decoration:none}a.gb2:hover{background:#36c;color:#fff !important}</style><script>window.google={kEI:"-AWFSZ6qFYuUswO9j5HIDQ",kEXPI:"17259,19547",kHL:"en"}; | ||
12 | +google.y={};google.x=function(e,g){google.y[e.id]=[e,g];return false};window.gbar={};(function(){var b=window.gbar,f,h;b.qs=function(a){var c=window.encodeURIComponent&&(document.forms[0].q||"").value;if(c)a.href=a.href.replace(/([?&])q=[^&]*|$/,function(i,g){return(g||"&")+"q="+encodeURIComponent(c)})};function j(a,c){a.visibility=h?"hidden":"visible";a.left=c+"px"}b.tg=function(a){a=a||window.event;var c=0,i,g=window.navExtra,d=document.getElementById("gbi"),e=a.target||a.srcElement;a.cancelBubble=true;if(!f){f=document.createElement(Array.every||window.createPopup?"iframe":"div");f.frameBorder="0";f.src="#";d.parentNode.appendChild(f).id="gbs";if(g)for(i in g)d.insertBefore(g[i],d.firstChild).className="gb2";document.onclick=b.close}if(e.className!="gb3")e=e.parentNode;do c+=e.offsetLeft;while(e=e.offsetParent);j(d.style,c);f.style.width=d.offsetWidth+"px";f.style.height=d.offsetHeight+"px";j(f.style,c);h=!h};b.close=function(a){h&&b.tg(a)}})();</script></head><body bgcolor=#ffffff text=#000000 link=#0000cc vlink=#551a8b alink=#ff0000 onload="document.f.q.focus();if(document.images)new Image().src='/images/nav_logo3.png'" topmargin=3 marginheight=3><div id=gbar><nobr><b class=gb1>Web</b> <a href="http://images.google.com/imghp?hl=en&tab=wi" onclick=gbar.qs(this) class=gb1>Images</a> <a href="http://maps.google.com/maps?hl=en&tab=wl" onclick=gbar.qs(this) class=gb1>Maps</a> <a href="http://news.google.com/nwshp?hl=en&tab=wn" onclick=gbar.qs(this) class=gb1>News</a> <a href="http://www.google.com/prdhp?hl=en&tab=wf" onclick=gbar.qs(this) class=gb1>Shopping</a> <a href="http://mail.google.com/mail/?hl=en&tab=wm" class=gb1>Gmail</a> <a href="http://www.google.com/intl/en/options/" onclick="this.blur();gbar.tg(event);return !1" class=gb3><u>more</u> <small>▼</small></a><div id=gbi> <a href="http://video.google.com/?hl=en&tab=wv" onclick=gbar.qs(this) class=gb2>Video</a> <a href="http://groups.google.com/grphp?hl=en&tab=wg" onclick=gbar.qs(this) class=gb2>Groups</a> <a href="http://books.google.com/bkshp?hl=en&tab=wp" onclick=gbar.qs(this) class=gb2>Books</a> <a href="http://scholar.google.com/schhp?hl=en&tab=ws" onclick=gbar.qs(this) class=gb2>Scholar</a> <a href="http://finance.google.com/finance?hl=en&tab=we" onclick=gbar.qs(this) class=gb2>Finance</a> <a href="http://blogsearch.google.com/?hl=en&tab=wb" onclick=gbar.qs(this) class=gb2>Blogs</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.youtube.com/?hl=en&tab=w1" onclick=gbar.qs(this) class=gb2>YouTube</a> <a href="http://www.google.com/calendar/render?hl=en&tab=wc" class=gb2>Calendar</a> <a href="http://picasaweb.google.com/home?hl=en&tab=wq" onclick=gbar.qs(this) class=gb2>Photos</a> <a href="http://docs.google.com/?hl=en&tab=wo" class=gb2>Documents</a> <a href="http://www.google.com/reader/view/?hl=en&tab=wy" class=gb2>Reader</a> <a href="http://sites.google.com/?hl=en&tab=w3" class=gb2>Sites</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.google.com/intl/en/options/" class=gb2>even more »</a></div> </nobr></div><div class=gbh style=left:0></div><div class=gbh style=right:0></div><div align=right id=guser style="font-size:84%;padding:0 0 4px" width=100%><nobr><a href="/url?sa=p&pref=ig&pval=3&q=http://www.google.com/ig%3Fhl%3Den%26source%3Diglk&usg=AFQjCNFA18XPfgb7dKnXfKz7x7g1GDH1tg">iGoogle</a> | <a href="https://www.google.com/accounts/Login?continue=http://www.google.com/&hl=en">Sign in</a></nobr></div><center><br clear=all id=lgpd><img alt="Google" height=110 src="/intl/en_ALL/images/logo.gif" width=276><br><br><form action="/search" name=f><table cellpadding=0 cellspacing=0><tr valign=top><td width=25%> </td><td align=center nowrap><input name=hl type=hidden value=en><input type=hidden name=ie value="ISO-8859-1"><input autocomplete="off" maxlength=2048 name=q size=55 title="Google Search" value=""><br><input name=btnG type=submit value="Google Search"><input name=btnI type=submit value="I'm Feeling Lucky"></td><td nowrap width=25%><font size=-2> <a href=/advanced_search?hl=en>Advanced Search</a><br> <a href=/preferences?hl=en>Preferences</a><br> <a href=/language_tools?hl=en>Language Tools</a></font></td></tr></table></form><br><font size=-1>Share what you know. <a href="/aclk?sa=L&ai=CYhslHwSFSZH6LIHusAPEsc2eBfv77nqP3YC9CsHZnNkTEAEgwVRQypDftPn_____AWDJBqoECU_QbUVlfOdxZw&num=1&sig=AGiWqtwRgqw8y_kza6RGKxBrCstaXkDJ7A&q=http://knol.google.com">Write a Knol</a>.</font><br><br><br><font size=-1><a href="/intl/en/ads/">Advertising Programs</a> - <a href="/services/">Business Solutions</a> - <a href="/intl/en/about.html">About Google</a></font><p><font size=-2>©2009 - <a href="/intl/en/privacy.html">Privacy</a></font></p></center></body><script>if(google.y)google.y.first=[];window.setTimeout(function(){var xjs=document.createElement('script');xjs.src='/extern_js/f/CgJlbhICdXMgACswCjgVLCswDjgELCswGDgDLA/L3N5xu59nDE.js';document.getElementsByTagName('head')[0].appendChild(xjs)},0);google.y.first.push(function(){google.ac.i(document.f,document.f.q,'','')})</script><script>function _gjp() {!(location.hash && _gjuc()) && setTimeout(_gjp, 500);}window._gjuc && _gjp();</script></html> | ||
0 | \ No newline at end of file | 13 | \ No newline at end of file |
vendor/gems/fakeweb-1.2.5/test/fixtures/google_response_with_transfer_encoding
0 → 100644
@@ -0,0 +1,17 @@ | @@ -0,0 +1,17 @@ | ||
1 | +HTTP/1.1 200 OK | ||
2 | +Cache-Control: private, max-age=0 | ||
3 | +Date: Sun, 01 Feb 2009 01:54:36 GMT | ||
4 | +Expires: -1 | ||
5 | +Content-Type: text/html; charset=ISO-8859-1 | ||
6 | +Set-Cookie: PREF=ID=4320bcaa30d097de:TM=1233453276:LM=1233453276:S=Eio39bg_nIabTxzL; expires=Tue, 01-Feb-2011 01:54:36 GMT; path=/; domain=.google.com | ||
7 | +Server: gws | ||
8 | +Transfer-Encoding: chunked | ||
9 | + | ||
10 | +fef | ||
11 | +<html><head><meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"><title>Google</title><script>var _gjwl=location;function _gjuc(){var a=_gjwl.hash;if(a.indexOf("&q=")>0||a.indexOf("#q=")>=0){a=a.substring(1);if(a.indexOf("#")==-1){for(var c=0;c<a.length;){var d=c;if(a.charAt(d)=="&")++d;var b=a.indexOf("&",d);if(b==-1)b=a.length;var e=a.substring(d,b);if(e.indexOf("fp=")==0){a=a.substring(0,c)+a.substring(b,a.length);b=c}else if(e=="cad=h")return 0;c=b}_gjwl.href="search?"+a+"&cad=h";return 1}}return 0}; | ||
12 | +window._gjuc && location.hash && _gjuc();</script><style>body,td,a,p,.h{font-family:arial,sans-serif}.h{color:#36c;font-size:20px}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}#gbar{height:22px;padding-left:2px}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}#gbi,#gbs{background:#fff;left:0;position:absolute;top:24px;visibility:hidden;z-index:1000}#gbi{border:1px solid;border-color:#c9d7f1 #36c #36c #a2bae7;z-index:1001}#guser{padding-bottom:7px !important}#gbar,#guser{font-size:13px;padding-top:1px !important}@media all{.gb1,.gb3{height:22px;margin-right:.73em;vertical-align:top}#gbar{float:left}}.gb2{display:block;padding:.2em .5em}a.gb1,a.gb2,a.gb3{color:#00c !important}.gb2,.gb3{text-decoration:none}a.gb2:hover{background:#36c;color:#fff !important}</style><script>window.google={kEI:"3ACFSYC6EKTcswOL4_nBDQ",kEXPI:"17259,19463",kHL:"en"}; | ||
13 | +google.y={};google.x=function(e,g){google.y[e.id]=[e,g];return false};window.gbar={};(function(){var b=window.gbar,f,h;b.qs=function(a){var c=window.encodeURIComponent&&(document.forms[0].q||"").value;if(c)a.href=a.href.replace(/([?&])q=[^&]*|$/,function(i,g){return(g||"&")+"q="+encodeURIComponent(c)})};function j(a,c){a.visibility=h?"hidden":"visible";a.left=c+"px"}b.tg=function(a){a=a||window.event;var c=0,i,g=window.navExtra,d=document.getElementById("gbi"),e=a.target||a.srcElement;a.cancelBubble=true;if(!f){f=document.createElement(Array.every||window.createPopup?"iframe":"div");f.frameBorder="0";f.src="#";d.parentNode.appendChild(f).id="gbs";if(g)for(i in g)d.insertBefore(g[i],d.firstChild).className="gb2";document.onclick=b.close}if(e.className!="gb3")e=e.parentNode;do c+=e.offsetLeft;while(e=e.offsetParent);j(d.style,c);f.style.width=d.offsetWidth+"px";f.style.height=d.offsetHeight+"px";j(f.style,c);h=!h};b.close=function(a){h&&b.tg(a)}})();</script></head><body bgcolor=#ffffff text=#000000 link=#0000cc vlink=#551a8b alink=#ff0000 onload="document.f.q.focus();if(document.images)new Image().src='/images/nav_logo3.png'" topmargin=3 marginheight=3><div id=gbar><nobr><b class=gb1>Web</b> <a href="http://images.google.com/imghp?hl=en&tab=wi" onclick=gbar.qs(this) class=gb1>Images</a> <a href="http://maps.google.com/maps?hl=en&tab=wl" onclick=gbar.qs(this) class=gb1>Maps</a> <a href="http://news.google.com/nwshp?hl=en&tab=wn" onclick=gbar.qs(this) class=gb1>News</a> <a href="http://www.google.com/prdhp?hl=en&tab=wf" onclick=gbar.qs(this) class=gb1>Shopping</a> <a href="http://mail.google.com/mail/?hl=en&tab=wm" class=gb1>Gmail</a> <a href="http://www.google.com/intl/en/options/" onclick="this.blur();gbar.tg(event);return !1" class=gb3><u>more</u> <small>▼</small></a><div id=gbi> <a href="http://video.google.com/?hl=en&tab=wv" onclick=gbar.qs(this) class=gb2>Video</a> <a href="http://groups.google.com/grphp?hl=en&tab=wg" onclick=gbar.qs(this) class=gb2>Groups</a> <a href="http://books.google.com/bkshp?hl=en&tab=wp" onclick=gbar.qs(this) class=gb2>Books</a> <a href="http://scholar.google.com/schhp?hl=en&tab=ws" onclick=gbar.qs(this) class=gb2>Scholar</a> <a href="http://finance.google.com/finance?hl=en&tab=we" onclick=gbar.qs(this) class=gb2>Finance</a> <a href="http://blogsearch.google.com/?hl=en&tab=wb" onclick=gbar.qs(this) class=gb2>Blogs</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.youtube.com/?hl=en&tab=w1" onclick=gbar.qs(this) class=gb2>YouTube</a> <a href="http://www.google.com/calendar/render?hl=en&tab=wc" class=gb2>Calendar</a> <a href="http | ||
14 | +a27 | ||
15 | +://picasaweb.google.com/home?hl=en&tab=wq" onclick=gbar.qs(this) class=gb2>Photos</a> <a href="http://docs.google.com/?hl=en&tab=wo" class=gb2>Documents</a> <a href="http://www.google.com/reader/view/?hl=en&tab=wy" class=gb2>Reader</a> <a href="http://sites.google.com/?hl=en&tab=w3" class=gb2>Sites</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.google.com/intl/en/options/" class=gb2>even more »</a></div> </nobr></div><div class=gbh style=left:0></div><div class=gbh style=right:0></div><div align=right id=guser style="font-size:84%;padding:0 0 4px" width=100%><nobr><a href="/url?sa=p&pref=ig&pval=3&q=http://www.google.com/ig%3Fhl%3Den%26source%3Diglk&usg=AFQjCNFA18XPfgb7dKnXfKz7x7g1GDH1tg">iGoogle</a> | <a href="https://www.google.com/accounts/Login?continue=http://www.google.com/&hl=en">Sign in</a></nobr></div><center><br clear=all id=lgpd><img alt="Google" height=110 src="/intl/en_ALL/images/logo.gif" width=276><br><br><form action="/search" name=f><table cellpadding=0 cellspacing=0><tr valign=top><td width=25%> </td><td align=center nowrap><input name=hl type=hidden value=en><input type=hidden name=ie value="ISO-8859-1"><input autocomplete="off" maxlength=2048 name=q size=55 title="Google Search" value=""><br><input name=btnG type=submit value="Google Search"><input name=btnI type=submit value="I'm Feeling Lucky"></td><td nowrap width=25%><font size=-2> <a href=/advanced_search?hl=en>Advanced Search</a><br> <a href=/preferences?hl=en>Preferences</a><br> <a href=/language_tools?hl=en>Language Tools</a></font></td></tr></table></form><br><font size=-1>Share what you know. <a href="/aclk?sa=L&ai=CFL7HzwCFSZCnCJSwsQPm842HB_v77nqP3YC9CsHZnNkTEAEgwVRQypDftPn_____AWDJBqoECU_Q1sTewQNSbw&num=1&sig=AGiWqtyz-UiOD3EpsSp4k3n8A7zooeg48g&q=http://knol.google.com">Write a Knol</a>.</font><br><br><br><font size=-1><a href="/intl/en/ads/">Advertising Programs</a> - <a href="/services/">Business Solutions</a> - <a href="/intl/en/about.html">About Google</a></font><p><font size=-2>©2009 - <a href="/intl/en/privacy.html">Privacy</a></font></p></center></body><script>if(google.y)google.y.first=[];window.setTimeout(function(){var xjs=document.createElement('script');xjs.src='/extern_js/f/CgJlbhICdXMgACswCjgVLCswDjgELCswGDgDLA/L3N5xu59nDE.js';document.getElementsByTagName('head')[0].appendChild(xjs)},0);google.y.first.push(function(){google.ac.i(document.f,document.f.q,'','')})</script><script>function _gjp() {!(location.hash && _gjuc()) && setTimeout(_gjp, 500);}window._gjuc && _gjp();</script></html> | ||
16 | +0 | ||
17 | + |
vendor/gems/fakeweb-1.2.5/test/fixtures/google_response_without_transfer_encoding
0 → 100644
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | +HTTP/1.0 200 OK | ||
2 | +Cache-Control: private, max-age=0 | ||
3 | +Date: Sun, 01 Feb 2009 01:55:33 GMT | ||
4 | +Expires: -1 | ||
5 | +Content-Type: text/html; charset=ISO-8859-1 | ||
6 | +Set-Cookie: PREF=ID=3c140c3eb4c4f516:TM=1233453333:LM=1233453333:S=OH7sElk2hOWkb9ot; expires=Tue, 01-Feb-2011 01:55:33 GMT; path=/; domain=.google.com | ||
7 | +Server: gws | ||
8 | + | ||
9 | +<html><head><meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"><title>Google</title><script>var _gjwl=location;function _gjuc(){var a=_gjwl.hash;if(a.indexOf("&q=")>0||a.indexOf("#q=")>=0){a=a.substring(1);if(a.indexOf("#")==-1){for(var c=0;c<a.length;){var d=c;if(a.charAt(d)=="&")++d;var b=a.indexOf("&",d);if(b==-1)b=a.length;var e=a.substring(d,b);if(e.indexOf("fp=")==0){a=a.substring(0,c)+a.substring(b,a.length);b=c}else if(e=="cad=h")return 0;c=b}_gjwl.href="search?"+a+"&cad=h";return 1}}return 0}; | ||
10 | +window._gjuc && location.hash && _gjuc();</script><style>body,td,a,p,.h{font-family:arial,sans-serif}.h{color:#36c;font-size:20px}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}#gbar{height:22px;padding-left:2px}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}#gbi,#gbs{background:#fff;left:0;position:absolute;top:24px;visibility:hidden;z-index:1000}#gbi{border:1px solid;border-color:#c9d7f1 #36c #36c #a2bae7;z-index:1001}#guser{padding-bottom:7px !important}#gbar,#guser{font-size:13px;padding-top:1px !important}@media all{.gb1,.gb3{height:22px;margin-right:.73em;vertical-align:top}#gbar{float:left}}.gb2{display:block;padding:.2em .5em}a.gb1,a.gb2,a.gb3{color:#00c !important}.gb2,.gb3{text-decoration:none}a.gb2:hover{background:#36c;color:#fff !important}</style><script>window.google={kEI:"FQGFSY2rG5eSswOKpsHeDQ",kEXPI:"17259",kHL:"en"}; | ||
11 | +google.y={};google.x=function(e,g){google.y[e.id]=[e,g];return false};window.gbar={};(function(){var b=window.gbar,f,h;b.qs=function(a){var c=window.encodeURIComponent&&(document.forms[0].q||"").value;if(c)a.href=a.href.replace(/([?&])q=[^&]*|$/,function(i,g){return(g||"&")+"q="+encodeURIComponent(c)})};function j(a,c){a.visibility=h?"hidden":"visible";a.left=c+"px"}b.tg=function(a){a=a||window.event;var c=0,i,g=window.navExtra,d=document.getElementById("gbi"),e=a.target||a.srcElement;a.cancelBubble=true;if(!f){f=document.createElement(Array.every||window.createPopup?"iframe":"div");f.frameBorder="0";f.src="#";d.parentNode.appendChild(f).id="gbs";if(g)for(i in g)d.insertBefore(g[i],d.firstChild).className="gb2";document.onclick=b.close}if(e.className!="gb3")e=e.parentNode;do c+=e.offsetLeft;while(e=e.offsetParent);j(d.style,c);f.style.width=d.offsetWidth+"px";f.style.height=d.offsetHeight+"px";j(f.style,c);h=!h};b.close=function(a){h&&b.tg(a)}})();</script></head><body bgcolor=#ffffff text=#000000 link=#0000cc vlink=#551a8b alink=#ff0000 onload="document.f.q.focus();if(document.images)new Image().src='/images/nav_logo3.png'" topmargin=3 marginheight=3><div id=gbar><nobr><b class=gb1>Web</b> <a href="http://images.google.com/imghp?hl=en&tab=wi" onclick=gbar.qs(this) class=gb1>Images</a> <a href="http://maps.google.com/maps?hl=en&tab=wl" onclick=gbar.qs(this) class=gb1>Maps</a> <a href="http://news.google.com/nwshp?hl=en&tab=wn" onclick=gbar.qs(this) class=gb1>News</a> <a href="http://www.google.com/prdhp?hl=en&tab=wf" onclick=gbar.qs(this) class=gb1>Shopping</a> <a href="http://mail.google.com/mail/?hl=en&tab=wm" class=gb1>Gmail</a> <a href="http://www.google.com/intl/en/options/" onclick="this.blur();gbar.tg(event);return !1" class=gb3><u>more</u> <small>▼</small></a><div id=gbi> <a href="http://video.google.com/?hl=en&tab=wv" onclick=gbar.qs(this) class=gb2>Video</a> <a href="http://groups.google.com/grphp?hl=en&tab=wg" onclick=gbar.qs(this) class=gb2>Groups</a> <a href="http://books.google.com/bkshp?hl=en&tab=wp" onclick=gbar.qs(this) class=gb2>Books</a> <a href="http://scholar.google.com/schhp?hl=en&tab=ws" onclick=gbar.qs(this) class=gb2>Scholar</a> <a href="http://finance.google.com/finance?hl=en&tab=we" onclick=gbar.qs(this) class=gb2>Finance</a> <a href="http://blogsearch.google.com/?hl=en&tab=wb" onclick=gbar.qs(this) class=gb2>Blogs</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.youtube.com/?hl=en&tab=w1" onclick=gbar.qs(this) class=gb2>YouTube</a> <a href="http://www.google.com/calendar/render?hl=en&tab=wc" class=gb2>Calendar</a> <a href="http://picasaweb.google.com/home?hl=en&tab=wq" onclick=gbar.qs(this) class=gb2>Photos</a> <a href="http://docs.google.com/?hl=en&tab=wo" class=gb2>Documents</a> <a href="http://www.google.com/reader/view/?hl=en&tab=wy" class=gb2>Reader</a> <a href="http://sites.google.com/?hl=en&tab=w3" class=gb2>Sites</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.google.com/intl/en/options/" class=gb2>even more »</a></div> </nobr></div><div class=gbh style=left:0></div><div class=gbh style=right:0></div><div align=right id=guser style="font-size:84%;padding:0 0 4px" width=100%><nobr><a href="/url?sa=p&pref=ig&pval=3&q=http://www.google.com/ig%3Fhl%3Den%26source%3Diglk&usg=AFQjCNFA18XPfgb7dKnXfKz7x7g1GDH1tg">iGoogle</a> | <a href="https://www.google.com/accounts/Login?continue=http://www.google.com/&hl=en">Sign in</a></nobr></div><center><br clear=all id=lgpd><img alt="Google" height=110 src="/intl/en_ALL/images/logo.gif" width=276><br><br><form action="/search" name=f><table cellpadding=0 cellspacing=0><tr valign=top><td width=25%> </td><td align=center nowrap><input name=hl type=hidden value=en><input type=hidden name=ie value="ISO-8859-1"><input autocomplete="off" maxlength=2048 name=q size=55 title="Google Search" value=""><br><input name=btnG type=submit value="Google Search"><input name=btnI type=submit value="I'm Feeling Lucky"></td><td nowrap width=25%><font size=-2> <a href=/advanced_search?hl=en>Advanced Search</a><br> <a href=/preferences?hl=en>Preferences</a><br> <a href=/language_tools?hl=en>Language Tools</a></font></td></tr></table></form><br><font size=-1>Share what you know. <a href="/aclk?sa=L&ai=ClyBp_v-EScTWD4W2tQOxoqSkB_v77nqP3YC9CsHZnNkTEAEgwVRQypDftPn_____AWDJBqoECU_QphTjHaZ5QA&num=1&sig=AGiWqtwtBqZ-zra3DJd_1chQKhKGf7lMVg&q=http://knol.google.com">Write a Knol</a>.</font><br><br><br><font size=-1><a href="/intl/en/ads/">Advertising Programs</a> - <a href="/services/">Business Solutions</a> - <a href="/intl/en/about.html">About Google</a></font><p><font size=-2>©2009 - <a href="/intl/en/privacy.html">Privacy</a></font></p></center></body><script>if(google.y)google.y.first=[];window.setTimeout(function(){var xjs=document.createElement('script');xjs.src='/extern_js/f/CgJlbhICdXMgACswCjgNLCswDjgELCswGDgDLA/oTKXc0xdkmY.js';document.getElementsByTagName('head')[0].appendChild(xjs)},0);google.y.first.push(function(){google.ac.i(document.f,document.f.q,'','')})</script><script>function _gjp() {!(location.hash && _gjuc()) && setTimeout(_gjp, 500);}window._gjuc && _gjp();</script></html> | ||
0 | \ No newline at end of file | 12 | \ No newline at end of file |
vendor/gems/fakeweb-1.2.5/test/fixtures/test_example.txt
0 → 100644
vendor/gems/fakeweb-1.2.5/test/test_allow_net_connect.rb
0 → 100644
@@ -0,0 +1,85 @@ | @@ -0,0 +1,85 @@ | ||
1 | +require File.join(File.dirname(__FILE__), "test_helper") | ||
2 | + | ||
3 | +class TestFakeWebAllowNetConnect < Test::Unit::TestCase | ||
4 | + | ||
5 | + def test_unregistered_requests_are_passed_through_when_allow_net_connect_is_true | ||
6 | + FakeWeb.allow_net_connect = true | ||
7 | + setup_expectations_for_real_apple_hot_news_request | ||
8 | + Net::HTTP.get(URI.parse("http://images.apple.com/main/rss/hotnews/hotnews.rss")) | ||
9 | + end | ||
10 | + | ||
11 | + def test_raises_for_unregistered_requests_when_allow_net_connect_is_false | ||
12 | + FakeWeb.allow_net_connect = false | ||
13 | + exception = assert_raise FakeWeb::NetConnectNotAllowedError do | ||
14 | + Net::HTTP.get(URI.parse("http://example.com/")) | ||
15 | + end | ||
16 | + end | ||
17 | + | ||
18 | + def test_exception_message_includes_unregistered_request_method_and_uri_but_no_default_port | ||
19 | + FakeWeb.allow_net_connect = false | ||
20 | + exception = assert_raise FakeWeb::NetConnectNotAllowedError do | ||
21 | + Net::HTTP.get(URI.parse("http://example.com/")) | ||
22 | + end | ||
23 | + assert exception.message.include?("GET http://example.com/") | ||
24 | + | ||
25 | + exception = assert_raise FakeWeb::NetConnectNotAllowedError do | ||
26 | + http = Net::HTTP.new("example.com", 443) | ||
27 | + http.use_ssl = true | ||
28 | + http.get("/") | ||
29 | + end | ||
30 | + assert exception.message.include?("GET https://example.com/") | ||
31 | + end | ||
32 | + | ||
33 | + def test_exception_message_includes_unregistered_request_port_when_not_default | ||
34 | + FakeWeb.allow_net_connect = false | ||
35 | + exception = assert_raise FakeWeb::NetConnectNotAllowedError do | ||
36 | + Net::HTTP.start("example.com", 8000) { |http| http.get("/") } | ||
37 | + end | ||
38 | + assert exception.message.include?("GET http://example.com:8000/") | ||
39 | + | ||
40 | + exception = assert_raise FakeWeb::NetConnectNotAllowedError do | ||
41 | + http = Net::HTTP.new("example.com", 4433) | ||
42 | + http.use_ssl = true | ||
43 | + http.get("/") | ||
44 | + end | ||
45 | + assert exception.message.include?("GET https://example.com:4433/") | ||
46 | + end | ||
47 | + | ||
48 | + def test_exception_message_includes_unregistered_request_port_when_not_default_with_path | ||
49 | + FakeWeb.allow_net_connect = false | ||
50 | + exception = assert_raise FakeWeb::NetConnectNotAllowedError do | ||
51 | + Net::HTTP.start("example.com", 8000) { |http| http.get("/test") } | ||
52 | + end | ||
53 | + assert exception.message.include?("GET http://example.com:8000/test") | ||
54 | + | ||
55 | + exception = assert_raise FakeWeb::NetConnectNotAllowedError do | ||
56 | + http = Net::HTTP.new("example.com", 4433) | ||
57 | + http.use_ssl = true | ||
58 | + http.get("/test") | ||
59 | + end | ||
60 | + assert exception.message.include?("GET https://example.com:4433/test") | ||
61 | + end | ||
62 | + | ||
63 | + def test_question_mark_method_returns_true_after_setting_allow_net_connect_to_true | ||
64 | + FakeWeb.allow_net_connect = true | ||
65 | + assert FakeWeb.allow_net_connect? | ||
66 | + end | ||
67 | + | ||
68 | + def test_question_mark_method_returns_false_after_setting_allow_net_connect_to_false | ||
69 | + FakeWeb.allow_net_connect = false | ||
70 | + assert !FakeWeb.allow_net_connect? | ||
71 | + end | ||
72 | + | ||
73 | +end | ||
74 | + | ||
75 | + | ||
76 | +class TestFakeWebAllowNetConnectWithCleanState < Test::Unit::TestCase | ||
77 | + # Our test_helper.rb sets allow_net_connect = false in an inherited #setup | ||
78 | + # method. Disable that here to test the default setting. | ||
79 | + def setup; end | ||
80 | + def teardown; end | ||
81 | + | ||
82 | + def test_allow_net_connect_is_true_by_default | ||
83 | + assert FakeWeb.allow_net_connect? | ||
84 | + end | ||
85 | +end |
@@ -0,0 +1,54 @@ | @@ -0,0 +1,54 @@ | ||
1 | +require File.join(File.dirname(__FILE__), "test_helper") | ||
2 | + | ||
3 | +class TestDeprecations < Test::Unit::TestCase | ||
4 | + | ||
5 | + def test_register_uri_without_method_argument_prints_deprecation_warning | ||
6 | + warning = capture_stderr do | ||
7 | + FakeWeb.register_uri("http://example.com", :body => "test") | ||
8 | + end | ||
9 | + assert_match /deprecation warning: fakeweb/i, warning | ||
10 | + end | ||
11 | + | ||
12 | + def test_registered_uri_without_method_argument_prints_deprecation_warning | ||
13 | + warning = capture_stderr do | ||
14 | + FakeWeb.registered_uri?("http://example.com") | ||
15 | + end | ||
16 | + assert_match /deprecation warning: fakeweb/i, warning | ||
17 | + end | ||
18 | + | ||
19 | + def test_response_for_without_method_argument_prints_deprecation_warning | ||
20 | + warning = capture_stderr do | ||
21 | + FakeWeb.response_for("http://example.com") | ||
22 | + end | ||
23 | + assert_match /deprecation warning: fakeweb/i, warning | ||
24 | + end | ||
25 | + | ||
26 | + def test_register_uri_without_method_argument_prints_deprecation_warning_with_correct_caller | ||
27 | + warning = capture_stderr do | ||
28 | + FakeWeb.register_uri("http://example.com", :body => "test") | ||
29 | + end | ||
30 | + assert_match /Called at.*?test_deprecations\.rb/i, warning | ||
31 | + end | ||
32 | + | ||
33 | + def test_register_uri_with_string_option_prints_deprecation_warning | ||
34 | + warning = capture_stderr do | ||
35 | + FakeWeb.register_uri(:get, "http://example.com", :string => "test") | ||
36 | + end | ||
37 | + assert_match /deprecation warning: fakeweb's :string option/i, warning | ||
38 | + end | ||
39 | + | ||
40 | + def test_register_uri_with_file_option_prints_deprecation_warning | ||
41 | + warning = capture_stderr do | ||
42 | + FakeWeb.register_uri(:get, "http://example.com", :file => File.dirname(__FILE__) + '/fixtures/test_example.txt') | ||
43 | + end | ||
44 | + assert_match /deprecation warning: fakeweb's :file option/i, warning | ||
45 | + end | ||
46 | + | ||
47 | + def test_register_uri_with_string_option_prints_deprecation_warning_with_correct_caller | ||
48 | + warning = capture_stderr do | ||
49 | + FakeWeb.register_uri(:get, "http://example.com", :string => "test") | ||
50 | + end | ||
51 | + assert_match /Called at.*?test_deprecations\.rb/i, warning | ||
52 | + end | ||
53 | + | ||
54 | +end |
vendor/gems/fakeweb-1.2.5/test/test_fake_authentication.rb
0 → 100644
@@ -0,0 +1,92 @@ | @@ -0,0 +1,92 @@ | ||
1 | +require File.join(File.dirname(__FILE__), "test_helper") | ||
2 | + | ||
3 | +class TestFakeAuthentication < Test::Unit::TestCase | ||
4 | + | ||
5 | + def test_register_uri_with_authentication | ||
6 | + FakeWeb.register_uri(:get, 'http://user:pass@mock/test_example.txt', :body => "example") | ||
7 | + assert FakeWeb.registered_uri?(:get, 'http://user:pass@mock/test_example.txt') | ||
8 | + end | ||
9 | + | ||
10 | + def test_register_uri_with_authentication_doesnt_trigger_without | ||
11 | + FakeWeb.register_uri(:get, 'http://user:pass@mock/test_example.txt', :body => "example") | ||
12 | + assert !FakeWeb.registered_uri?(:get, 'http://mock/test_example.txt') | ||
13 | + end | ||
14 | + | ||
15 | + def test_register_uri_with_authentication_doesnt_trigger_with_incorrect_credentials | ||
16 | + FakeWeb.register_uri(:get, 'http://user:pass@mock/test_example.txt', :body => "example") | ||
17 | + assert !FakeWeb.registered_uri?(:get, 'http://user:wrong@mock/test_example.txt') | ||
18 | + end | ||
19 | + | ||
20 | + def test_unauthenticated_request | ||
21 | + FakeWeb.register_uri(:get, 'http://mock/auth.txt', :body => 'unauthorized') | ||
22 | + http = Net::HTTP.new('mock', 80) | ||
23 | + req = Net::HTTP::Get.new('/auth.txt') | ||
24 | + assert_equal 'unauthorized', http.request(req).body | ||
25 | + end | ||
26 | + | ||
27 | + def test_authenticated_request | ||
28 | + FakeWeb.register_uri(:get, 'http://user:pass@mock/auth.txt', :body => 'authorized') | ||
29 | + http = Net::HTTP.new('mock',80) | ||
30 | + req = Net::HTTP::Get.new('/auth.txt') | ||
31 | + req.basic_auth 'user', 'pass' | ||
32 | + assert_equal 'authorized', http.request(req).body | ||
33 | + end | ||
34 | + | ||
35 | + def test_authenticated_request_where_only_userinfo_differs | ||
36 | + FakeWeb.register_uri(:get, 'http://user:pass@mock/auth.txt', :body => 'first user') | ||
37 | + FakeWeb.register_uri(:get, 'http://user2:pass@mock/auth.txt', :body => 'second user') | ||
38 | + http = Net::HTTP.new('mock') | ||
39 | + req = Net::HTTP::Get.new('/auth.txt') | ||
40 | + req.basic_auth 'user2', 'pass' | ||
41 | + assert_equal 'second user', http.request(req).body | ||
42 | + end | ||
43 | + | ||
44 | + def test_basic_auth_support_is_transparent_to_oauth | ||
45 | + FakeWeb.register_uri(:get, "http://sp.example.com/protected", :body => "secret") | ||
46 | + | ||
47 | + # from http://oauth.net/core/1.0/#auth_header | ||
48 | + auth_header = <<-HEADER | ||
49 | + OAuth realm="http://sp.example.com/", | ||
50 | + oauth_consumer_key="0685bd9184jfhq22", | ||
51 | + oauth_token="ad180jjd733klru7", | ||
52 | + oauth_signature_method="HMAC-SHA1", | ||
53 | + oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D", | ||
54 | + oauth_timestamp="137131200", | ||
55 | + oauth_nonce="4572616e48616d6d65724c61686176", | ||
56 | + oauth_version="1.0" | ||
57 | + HEADER | ||
58 | + auth_header.gsub!(/\s+/, " ").strip! | ||
59 | + | ||
60 | + http = Net::HTTP.new("sp.example.com", 80) | ||
61 | + response = nil | ||
62 | + http.start do |request| | ||
63 | + response = request.get("/protected", {"authorization" => auth_header}) | ||
64 | + end | ||
65 | + assert_equal "secret", response.body | ||
66 | + end | ||
67 | + | ||
68 | + def test_basic_auth_when_userinfo_contains_allowed_unencoded_characters | ||
69 | + FakeWeb.register_uri(:get, "http://roses&hel1o,(+$):so;longs=@example.com", :body => "authorized") | ||
70 | + http = Net::HTTP.new("example.com") | ||
71 | + request = Net::HTTP::Get.new("/") | ||
72 | + request.basic_auth("roses&hel1o,(+$)", "so;longs=") | ||
73 | + assert_equal "authorized", http.request(request).body | ||
74 | + end | ||
75 | + | ||
76 | + def test_basic_auth_when_userinfo_contains_encoded_at_sign | ||
77 | + FakeWeb.register_uri(:get, "http://user%40example.com:secret@example.com", :body => "authorized") | ||
78 | + http = Net::HTTP.new("example.com") | ||
79 | + request = Net::HTTP::Get.new("/") | ||
80 | + request.basic_auth("user@example.com", "secret") | ||
81 | + assert_equal "authorized", http.request(request).body | ||
82 | + end | ||
83 | + | ||
84 | + def test_basic_auth_when_userinfo_contains_allowed_encoded_characters | ||
85 | + FakeWeb.register_uri(:get, "http://us%20er:sec%20%2F%2Fret%3F@example.com", :body => "authorized") | ||
86 | + http = Net::HTTP.new("example.com") | ||
87 | + request = Net::HTTP::Get.new("/") | ||
88 | + request.basic_auth("us er", "sec //ret?") | ||
89 | + assert_equal "authorized", http.request(request).body | ||
90 | + end | ||
91 | + | ||
92 | +end |
@@ -0,0 +1,518 @@ | @@ -0,0 +1,518 @@ | ||
1 | +require File.join(File.dirname(__FILE__), "test_helper") | ||
2 | + | ||
3 | +class TestFakeWeb < Test::Unit::TestCase | ||
4 | + | ||
5 | + def test_register_uri | ||
6 | + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => "example") | ||
7 | + assert FakeWeb.registered_uri?(:get, 'http://mock/test_example.txt') | ||
8 | + end | ||
9 | + | ||
10 | + def test_register_uri_with_wrong_number_of_arguments | ||
11 | + assert_raises ArgumentError do | ||
12 | + FakeWeb.register_uri("http://example.com") | ||
13 | + end | ||
14 | + assert_raises ArgumentError do | ||
15 | + FakeWeb.register_uri(:get, "http://example.com", "/example", :body => "example") | ||
16 | + end | ||
17 | + end | ||
18 | + | ||
19 | + def test_registered_uri_with_wrong_number_of_arguments | ||
20 | + assert_raises ArgumentError do | ||
21 | + FakeWeb.registered_uri? | ||
22 | + end | ||
23 | + assert_raises ArgumentError do | ||
24 | + FakeWeb.registered_uri?(:get, "http://example.com", "/example") | ||
25 | + end | ||
26 | + end | ||
27 | + | ||
28 | + def test_response_for_with_wrong_number_of_arguments | ||
29 | + assert_raises ArgumentError do | ||
30 | + FakeWeb.response_for | ||
31 | + end | ||
32 | + assert_raises ArgumentError do | ||
33 | + FakeWeb.response_for(:get, "http://example.com", "/example") | ||
34 | + end | ||
35 | + end | ||
36 | + | ||
37 | + def test_register_uri_without_domain_name | ||
38 | + assert_raises URI::InvalidURIError do | ||
39 | + FakeWeb.register_uri(:get, 'test_example2.txt', File.dirname(__FILE__) + '/fixtures/test_example.txt') | ||
40 | + end | ||
41 | + end | ||
42 | + | ||
43 | + def test_register_uri_with_port_and_check_with_port | ||
44 | + FakeWeb.register_uri(:get, 'http://example.com:3000/', :body => 'foo') | ||
45 | + assert FakeWeb.registered_uri?(:get, 'http://example.com:3000/') | ||
46 | + end | ||
47 | + | ||
48 | + def test_register_uri_with_port_and_check_without_port | ||
49 | + FakeWeb.register_uri(:get, 'http://example.com:3000/', :body => 'foo') | ||
50 | + assert !FakeWeb.registered_uri?(:get, 'http://example.com/') | ||
51 | + end | ||
52 | + | ||
53 | + def test_register_uri_with_default_port_for_http_and_check_without_port | ||
54 | + FakeWeb.register_uri(:get, 'http://example.com:80/', :body => 'foo') | ||
55 | + assert FakeWeb.registered_uri?(:get, 'http://example.com/') | ||
56 | + end | ||
57 | + | ||
58 | + def test_register_uri_with_default_port_for_https_and_check_without_port | ||
59 | + FakeWeb.register_uri(:get, 'https://example.com:443/', :body => 'foo') | ||
60 | + assert FakeWeb.registered_uri?(:get, 'https://example.com/') | ||
61 | + end | ||
62 | + | ||
63 | + def test_register_uri_with_no_port_for_http_and_check_with_default_port | ||
64 | + FakeWeb.register_uri(:get, 'http://example.com/', :body => 'foo') | ||
65 | + assert FakeWeb.registered_uri?(:get, 'http://example.com:80/') | ||
66 | + end | ||
67 | + | ||
68 | + def test_register_uri_with_no_port_for_https_and_check_with_default_port | ||
69 | + FakeWeb.register_uri(:get, 'https://example.com/', :body => 'foo') | ||
70 | + assert FakeWeb.registered_uri?(:get, 'https://example.com:443/') | ||
71 | + end | ||
72 | + | ||
73 | + def test_register_uri_with_no_port_for_https_and_check_with_443_on_http | ||
74 | + FakeWeb.register_uri(:get, 'https://example.com/', :body => 'foo') | ||
75 | + assert !FakeWeb.registered_uri?(:get, 'http://example.com:443/') | ||
76 | + end | ||
77 | + | ||
78 | + def test_register_uri_with_no_port_for_http_and_check_with_80_on_https | ||
79 | + FakeWeb.register_uri(:get, 'http://example.com/', :body => 'foo') | ||
80 | + assert !FakeWeb.registered_uri?(:get, 'https://example.com:80/') | ||
81 | + end | ||
82 | + | ||
83 | + def test_register_uri_for_any_method_explicitly | ||
84 | + FakeWeb.register_uri(:any, "http://example.com/rpc_endpoint", :body => "OK") | ||
85 | + assert FakeWeb.registered_uri?(:get, "http://example.com/rpc_endpoint") | ||
86 | + assert FakeWeb.registered_uri?(:post, "http://example.com/rpc_endpoint") | ||
87 | + assert FakeWeb.registered_uri?(:put, "http://example.com/rpc_endpoint") | ||
88 | + assert FakeWeb.registered_uri?(:delete, "http://example.com/rpc_endpoint") | ||
89 | + assert FakeWeb.registered_uri?(:any, "http://example.com/rpc_endpoint") | ||
90 | + capture_stderr do # silence deprecation warning | ||
91 | + assert FakeWeb.registered_uri?("http://example.com/rpc_endpoint") | ||
92 | + end | ||
93 | + end | ||
94 | + | ||
95 | + def test_register_uri_for_get_method_only | ||
96 | + FakeWeb.register_uri(:get, "http://example.com/users", :body => "User list") | ||
97 | + assert FakeWeb.registered_uri?(:get, "http://example.com/users") | ||
98 | + assert !FakeWeb.registered_uri?(:post, "http://example.com/users") | ||
99 | + assert !FakeWeb.registered_uri?(:put, "http://example.com/users") | ||
100 | + assert !FakeWeb.registered_uri?(:delete, "http://example.com/users") | ||
101 | + assert !FakeWeb.registered_uri?(:any, "http://example.com/users") | ||
102 | + capture_stderr do # silence deprecation warning | ||
103 | + assert !FakeWeb.registered_uri?("http://example.com/users") | ||
104 | + end | ||
105 | + end | ||
106 | + | ||
107 | + def test_response_for_with_registered_uri | ||
108 | + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => File.dirname(__FILE__) + '/fixtures/test_example.txt') | ||
109 | + assert_equal 'test example content', FakeWeb.response_for(:get, 'http://mock/test_example.txt').body | ||
110 | + end | ||
111 | + | ||
112 | + def test_response_for_with_unknown_uri | ||
113 | + assert_nil FakeWeb.response_for(:get, 'http://example.com/') | ||
114 | + end | ||
115 | + | ||
116 | + def test_response_for_with_put_method | ||
117 | + FakeWeb.register_uri(:put, "http://example.com", :body => "response") | ||
118 | + assert_equal 'response', FakeWeb.response_for(:put, "http://example.com").body | ||
119 | + end | ||
120 | + | ||
121 | + def test_response_for_with_any_method_explicitly | ||
122 | + FakeWeb.register_uri(:any, "http://example.com", :body => "response") | ||
123 | + assert_equal 'response', FakeWeb.response_for(:get, "http://example.com").body | ||
124 | + assert_equal 'response', FakeWeb.response_for(:any, "http://example.com").body | ||
125 | + end | ||
126 | + | ||
127 | + def test_content_for_registered_uri_with_port_and_request_with_port | ||
128 | + FakeWeb.register_uri(:get, 'http://example.com:3000/', :body => 'test example content') | ||
129 | + response = Net::HTTP.start('example.com', 3000) { |http| http.get('/') } | ||
130 | + assert_equal 'test example content', response.body | ||
131 | + end | ||
132 | + | ||
133 | + def test_content_for_registered_uri_with_default_port_for_http_and_request_without_port | ||
134 | + FakeWeb.register_uri(:get, 'http://example.com:80/', :body => 'test example content') | ||
135 | + response = Net::HTTP.start('example.com') { |http| http.get('/') } | ||
136 | + assert_equal 'test example content', response.body | ||
137 | + end | ||
138 | + | ||
139 | + def test_content_for_registered_uri_with_no_port_for_http_and_request_with_default_port | ||
140 | + FakeWeb.register_uri(:get, 'http://example.com/', :body => 'test example content') | ||
141 | + response = Net::HTTP.start('example.com', 80) { |http| http.get('/') } | ||
142 | + assert_equal 'test example content', response.body | ||
143 | + end | ||
144 | + | ||
145 | + def test_content_for_registered_uri_with_default_port_for_https_and_request_with_default_port | ||
146 | + FakeWeb.register_uri(:get, 'https://example.com:443/', :body => 'test example content') | ||
147 | + http = Net::HTTP.new('example.com', 443) | ||
148 | + http.use_ssl = true | ||
149 | + response = http.get('/') | ||
150 | + assert_equal 'test example content', response.body | ||
151 | + end | ||
152 | + | ||
153 | + def test_content_for_registered_uri_with_no_port_for_https_and_request_with_default_port | ||
154 | + FakeWeb.register_uri(:get, 'https://example.com/', :body => 'test example content') | ||
155 | + http = Net::HTTP.new('example.com', 443) | ||
156 | + http.use_ssl = true | ||
157 | + response = http.get('/') | ||
158 | + assert_equal 'test example content', response.body | ||
159 | + end | ||
160 | + | ||
161 | + def test_content_for_registered_uris_with_ports_on_same_domain_and_request_without_port | ||
162 | + FakeWeb.register_uri(:get, 'http://example.com:3000/', :body => 'port 3000') | ||
163 | + FakeWeb.register_uri(:get, 'http://example.com/', :body => 'port 80') | ||
164 | + response = Net::HTTP.start('example.com') { |http| http.get('/') } | ||
165 | + assert_equal 'port 80', response.body | ||
166 | + end | ||
167 | + | ||
168 | + def test_content_for_registered_uris_with_ports_on_same_domain_and_request_with_port | ||
169 | + FakeWeb.register_uri(:get, 'http://example.com:3000/', :body => 'port 3000') | ||
170 | + FakeWeb.register_uri(:get, 'http://example.com/', :body => 'port 80') | ||
171 | + response = Net::HTTP.start('example.com', 3000) { |http| http.get('/') } | ||
172 | + assert_equal 'port 3000', response.body | ||
173 | + end | ||
174 | + | ||
175 | + def test_content_for_registered_uri_with_get_method_only | ||
176 | + FakeWeb.allow_net_connect = false | ||
177 | + FakeWeb.register_uri(:get, "http://example.com/", :body => "test example content") | ||
178 | + http = Net::HTTP.new('example.com') | ||
179 | + assert_equal 'test example content', http.get('/').body | ||
180 | + assert_raises(FakeWeb::NetConnectNotAllowedError) { http.post('/', nil) } | ||
181 | + assert_raises(FakeWeb::NetConnectNotAllowedError) { http.put('/', nil) } | ||
182 | + assert_raises(FakeWeb::NetConnectNotAllowedError) { http.delete('/') } | ||
183 | + end | ||
184 | + | ||
185 | + def test_content_for_registered_uri_with_any_method_explicitly | ||
186 | + FakeWeb.allow_net_connect = false | ||
187 | + FakeWeb.register_uri(:any, "http://example.com/", :body => "test example content") | ||
188 | + http = Net::HTTP.new('example.com') | ||
189 | + assert_equal 'test example content', http.get('/').body | ||
190 | + assert_equal 'test example content', http.post('/', nil).body | ||
191 | + assert_equal 'test example content', http.put('/', nil).body | ||
192 | + assert_equal 'test example content', http.delete('/').body | ||
193 | + end | ||
194 | + | ||
195 | + def test_content_for_registered_uri_with_any_method_implicitly | ||
196 | + FakeWeb.allow_net_connect = false | ||
197 | + capture_stderr do # silence deprecation warning | ||
198 | + FakeWeb.register_uri("http://example.com/", :body => "test example content") | ||
199 | + end | ||
200 | + | ||
201 | + http = Net::HTTP.new('example.com') | ||
202 | + assert_equal 'test example content', http.get('/').body | ||
203 | + assert_equal 'test example content', http.post('/', nil).body | ||
204 | + assert_equal 'test example content', http.put('/', nil).body | ||
205 | + assert_equal 'test example content', http.delete('/').body | ||
206 | + end | ||
207 | + | ||
208 | + def test_mock_request_with_block | ||
209 | + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => File.dirname(__FILE__) + '/fixtures/test_example.txt') | ||
210 | + response = Net::HTTP.start('mock') { |http| http.get('/test_example.txt') } | ||
211 | + assert_equal 'test example content', response.body | ||
212 | + end | ||
213 | + | ||
214 | + def test_request_with_registered_body_yields_the_response_body_to_a_request_block | ||
215 | + FakeWeb.register_uri(:get, "http://example.com", :body => "content") | ||
216 | + body = nil | ||
217 | + Net::HTTP.start("example.com") do |http| | ||
218 | + http.get("/") do |response_body| | ||
219 | + body = response_body | ||
220 | + end | ||
221 | + end | ||
222 | + assert_equal "content", body | ||
223 | + end | ||
224 | + | ||
225 | + def test_request_with_registered_response_yields_the_response_body_to_a_request_block | ||
226 | + fake_response = Net::HTTPOK.new('1.1', '200', 'OK') | ||
227 | + fake_response.instance_variable_set(:@body, "content") | ||
228 | + FakeWeb.register_uri(:get, 'http://example.com', :response => fake_response) | ||
229 | + body = nil | ||
230 | + Net::HTTP.start("example.com") do |http| | ||
231 | + http.get("/") do |response_body| | ||
232 | + body = response_body | ||
233 | + end | ||
234 | + end | ||
235 | + assert_equal "content", body | ||
236 | + end | ||
237 | + | ||
238 | + def test_mock_request_with_undocumented_full_uri_argument_style | ||
239 | + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => File.dirname(__FILE__) + '/fixtures/test_example.txt') | ||
240 | + response = Net::HTTP.start('mock') { |query| query.get('http://mock/test_example.txt') } | ||
241 | + assert_equal 'test example content', response.body | ||
242 | + end | ||
243 | + | ||
244 | + def test_mock_request_with_undocumented_full_uri_argument_style_and_query | ||
245 | + FakeWeb.register_uri(:get, 'http://mock/test_example.txt?a=b', :body => 'test query content') | ||
246 | + response = Net::HTTP.start('mock') { |query| query.get('http://mock/test_example.txt?a=b') } | ||
247 | + assert_equal 'test query content', response.body | ||
248 | + end | ||
249 | + | ||
250 | + def test_mock_post | ||
251 | + FakeWeb.register_uri(:post, 'http://mock/test_example.txt', :body => File.dirname(__FILE__) + '/fixtures/test_example.txt') | ||
252 | + response = Net::HTTP.start('mock') { |query| query.post('/test_example.txt', '') } | ||
253 | + assert_equal 'test example content', response.body | ||
254 | + end | ||
255 | + | ||
256 | + def test_mock_post_with_string_as_registered_uri | ||
257 | + FakeWeb.register_uri(:post, 'http://mock/test_string.txt', :body => 'foo') | ||
258 | + response = Net::HTTP.start('mock') { |query| query.post('/test_string.txt', '') } | ||
259 | + assert_equal 'foo', response.body | ||
260 | + end | ||
261 | + | ||
262 | + def test_mock_get_with_request_as_registered_uri | ||
263 | + fake_response = Net::HTTPOK.new('1.1', '200', 'OK') | ||
264 | + FakeWeb.register_uri(:get, 'http://mock/test_response', :response => fake_response) | ||
265 | + response = Net::HTTP.start('mock') { |query| query.get('/test_response') } | ||
266 | + assert_equal fake_response, response | ||
267 | + end | ||
268 | + | ||
269 | + def test_mock_get_with_request_from_file_as_registered_uri | ||
270 | + FakeWeb.register_uri(:get, 'http://www.google.com/', :response => File.dirname(__FILE__) + '/fixtures/google_response_without_transfer_encoding') | ||
271 | + response = Net::HTTP.start('www.google.com') { |query| query.get('/') } | ||
272 | + assert_equal '200', response.code | ||
273 | + assert response.body.include?('<title>Google</title>') | ||
274 | + end | ||
275 | + | ||
276 | + def test_mock_post_with_request_from_file_as_registered_uri | ||
277 | + FakeWeb.register_uri(:post, 'http://www.google.com/', :response => File.dirname(__FILE__) + '/fixtures/google_response_without_transfer_encoding') | ||
278 | + response = Net::HTTP.start('www.google.com') { |query| query.post('/', '') } | ||
279 | + assert_equal "200", response.code | ||
280 | + assert response.body.include?('<title>Google</title>') | ||
281 | + end | ||
282 | + | ||
283 | + def test_proxy_request | ||
284 | + FakeWeb.register_uri(:get, 'http://www.example.com/', :body => "hello world") | ||
285 | + FakeWeb.register_uri(:get, 'http://your.proxy.host/', :body => "lala") | ||
286 | + | ||
287 | + response = nil | ||
288 | + Net::HTTP::Proxy('your.proxy.host', 8080).start('www.example.com') do |http| | ||
289 | + response = http.get('/') | ||
290 | + end | ||
291 | + assert_equal "hello world", response.body | ||
292 | + end | ||
293 | + | ||
294 | + def test_https_request | ||
295 | + FakeWeb.register_uri(:get, 'https://www.example.com/', :body => "Hello World") | ||
296 | + http = Net::HTTP.new('www.example.com', 443) | ||
297 | + http.use_ssl = true | ||
298 | + response = http.get('/') | ||
299 | + assert_equal "Hello World", response.body | ||
300 | + end | ||
301 | + | ||
302 | + def test_register_unimplemented_response | ||
303 | + FakeWeb.register_uri(:get, 'http://mock/unimplemented', :response => 1) | ||
304 | + assert_raises StandardError do | ||
305 | + Net::HTTP.start('mock') { |q| q.get('/unimplemented') } | ||
306 | + end | ||
307 | + end | ||
308 | + | ||
309 | + def test_real_http_request | ||
310 | + FakeWeb.allow_net_connect = true | ||
311 | + setup_expectations_for_real_apple_hot_news_request | ||
312 | + | ||
313 | + resp = nil | ||
314 | + Net::HTTP.start('images.apple.com') do |query| | ||
315 | + resp = query.get('/main/rss/hotnews/hotnews.rss') | ||
316 | + end | ||
317 | + assert resp.body.include?('Apple') | ||
318 | + assert resp.body.include?('News') | ||
319 | + end | ||
320 | + | ||
321 | + def test_real_http_request_with_undocumented_full_uri_argument_style | ||
322 | + FakeWeb.allow_net_connect = true | ||
323 | + setup_expectations_for_real_apple_hot_news_request(:path => 'http://images.apple.com/main/rss/hotnews/hotnews.rss') | ||
324 | + | ||
325 | + resp = nil | ||
326 | + Net::HTTP.start('images.apple.com') do |query| | ||
327 | + resp = query.get('http://images.apple.com/main/rss/hotnews/hotnews.rss') | ||
328 | + end | ||
329 | + assert resp.body.include?('Apple') | ||
330 | + assert resp.body.include?('News') | ||
331 | + end | ||
332 | + | ||
333 | + def test_real_https_request | ||
334 | + FakeWeb.allow_net_connect = true | ||
335 | + setup_expectations_for_real_apple_hot_news_request(:port => 443) | ||
336 | + | ||
337 | + http = Net::HTTP.new('images.apple.com', 443) | ||
338 | + http.use_ssl = true | ||
339 | + http.verify_mode = OpenSSL::SSL::VERIFY_NONE # silence certificate warning | ||
340 | + response = http.get('/main/rss/hotnews/hotnews.rss') | ||
341 | + assert response.body.include?('Apple') | ||
342 | + assert response.body.include?('News') | ||
343 | + end | ||
344 | + | ||
345 | + def test_real_request_on_same_domain_as_mock | ||
346 | + FakeWeb.allow_net_connect = true | ||
347 | + setup_expectations_for_real_apple_hot_news_request | ||
348 | + | ||
349 | + FakeWeb.register_uri(:get, 'http://images.apple.com/test_string.txt', :body => 'foo') | ||
350 | + | ||
351 | + resp = nil | ||
352 | + Net::HTTP.start('images.apple.com') do |query| | ||
353 | + resp = query.get('/main/rss/hotnews/hotnews.rss') | ||
354 | + end | ||
355 | + assert resp.body.include?('Apple') | ||
356 | + assert resp.body.include?('News') | ||
357 | + end | ||
358 | + | ||
359 | + def test_mock_request_on_real_domain | ||
360 | + FakeWeb.register_uri(:get, 'http://images.apple.com/test_string.txt', :body => 'foo') | ||
361 | + resp = nil | ||
362 | + Net::HTTP.start('images.apple.com') do |query| | ||
363 | + resp = query.get('/test_string.txt') | ||
364 | + end | ||
365 | + assert_equal 'foo', resp.body | ||
366 | + end | ||
367 | + | ||
368 | + def test_mock_post_that_raises_exception | ||
369 | + FakeWeb.register_uri(:post, 'http://mock/raising_exception.txt', :exception => StandardError) | ||
370 | + assert_raises(StandardError) do | ||
371 | + Net::HTTP.start('mock') do |query| | ||
372 | + query.post('/raising_exception.txt', 'some data') | ||
373 | + end | ||
374 | + end | ||
375 | + end | ||
376 | + | ||
377 | + def test_mock_post_that_raises_an_http_error | ||
378 | + FakeWeb.register_uri(:post, 'http://mock/raising_exception.txt', :exception => Net::HTTPError) | ||
379 | + assert_raises(Net::HTTPError) do | ||
380 | + Net::HTTP.start('mock') do |query| | ||
381 | + query.post('/raising_exception.txt', '') | ||
382 | + end | ||
383 | + end | ||
384 | + end | ||
385 | + | ||
386 | + def test_raising_an_exception_that_requires_an_argument_to_instantiate | ||
387 | + FakeWeb.register_uri(:get, "http://example.com/timeout.txt", :exception => Timeout::Error) | ||
388 | + assert_raises(Timeout::Error) do | ||
389 | + Net::HTTP.get(URI.parse("http://example.com/timeout.txt")) | ||
390 | + end | ||
391 | + end | ||
392 | + | ||
393 | + def test_mock_instance_syntax | ||
394 | + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => File.dirname(__FILE__) + '/fixtures/test_example.txt') | ||
395 | + response = nil | ||
396 | + uri = URI.parse('http://mock/test_example.txt') | ||
397 | + http = Net::HTTP.new(uri.host, uri.port) | ||
398 | + response = http.start do | ||
399 | + http.get(uri.path) | ||
400 | + end | ||
401 | + | ||
402 | + assert_equal 'test example content', response.body | ||
403 | + end | ||
404 | + | ||
405 | + def test_mock_via_nil_proxy | ||
406 | + response = nil | ||
407 | + proxy_address = nil | ||
408 | + proxy_port = nil | ||
409 | + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => File.dirname(__FILE__) + '/fixtures/test_example.txt') | ||
410 | + uri = URI.parse('http://mock/test_example.txt') | ||
411 | + http = Net::HTTP::Proxy(proxy_address, proxy_port).new( | ||
412 | + uri.host, (uri.port or 80)) | ||
413 | + response = http.start do | ||
414 | + http.get(uri.path) | ||
415 | + end | ||
416 | + | ||
417 | + assert_equal 'test example content', response.body | ||
418 | + end | ||
419 | + | ||
420 | + def test_response_type | ||
421 | + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => "test") | ||
422 | + response = Net::HTTP.start('mock') { |http| http.get('/test_example.txt') } | ||
423 | + assert_kind_of Net::HTTPSuccess, response | ||
424 | + end | ||
425 | + | ||
426 | + def test_mock_request_that_raises_an_http_error_with_a_specific_status | ||
427 | + FakeWeb.register_uri(:get, 'http://mock/raising_exception.txt', :exception => Net::HTTPError, :status => ['404', 'Not Found']) | ||
428 | + exception = assert_raises(Net::HTTPError) do | ||
429 | + Net::HTTP.start('mock') { |http| http.get('/raising_exception.txt') } | ||
430 | + end | ||
431 | + assert_equal '404', exception.response.code | ||
432 | + assert_equal 'Not Found', exception.response.msg | ||
433 | + end | ||
434 | + | ||
435 | + def test_mock_rotate_responses | ||
436 | + FakeWeb.register_uri(:get, 'http://mock/multiple_test_example.txt', | ||
437 | + [ {:body => File.dirname(__FILE__) + '/fixtures/test_example.txt', :times => 2}, | ||
438 | + {:body => "thrice", :times => 3}, | ||
439 | + {:body => "ever_more"} ]) | ||
440 | + | ||
441 | + uri = URI.parse('http://mock/multiple_test_example.txt') | ||
442 | + 2.times { assert_equal 'test example content', Net::HTTP.get(uri) } | ||
443 | + 3.times { assert_equal 'thrice', Net::HTTP.get(uri) } | ||
444 | + 4.times { assert_equal 'ever_more', Net::HTTP.get(uri) } | ||
445 | + end | ||
446 | + | ||
447 | + def test_mock_request_using_response_with_transfer_encoding_header_has_valid_transfer_encoding_header | ||
448 | + FakeWeb.register_uri(:get, 'http://www.google.com/', :response => File.dirname(__FILE__) + '/fixtures/google_response_with_transfer_encoding') | ||
449 | + response = Net::HTTP.start('www.google.com') { |query| query.get('/') } | ||
450 | + assert_not_nil response['transfer-encoding'] | ||
451 | + assert response['transfer-encoding'] == 'chunked' | ||
452 | + end | ||
453 | + | ||
454 | + def test_mock_request_using_response_without_transfer_encoding_header_does_not_have_a_transfer_encoding_header | ||
455 | + FakeWeb.register_uri(:get, 'http://www.google.com/', :response => File.dirname(__FILE__) + '/fixtures/google_response_without_transfer_encoding') | ||
456 | + response = nil | ||
457 | + response = Net::HTTP.start('www.google.com') { |query| query.get('/') } | ||
458 | + assert !response.key?('transfer-encoding') | ||
459 | + end | ||
460 | + | ||
461 | + def test_mock_request_using_response_from_curl_has_original_transfer_encoding_header | ||
462 | + FakeWeb.register_uri(:get, 'http://www.google.com/', :response => File.dirname(__FILE__) + '/fixtures/google_response_from_curl') | ||
463 | + response = Net::HTTP.start('www.google.com') { |query| query.get('/') } | ||
464 | + assert_not_nil response['transfer-encoding'] | ||
465 | + assert response['transfer-encoding'] == 'chunked' | ||
466 | + end | ||
467 | + | ||
468 | + def test_txt_file_should_have_three_lines | ||
469 | + FakeWeb.register_uri(:get, 'http://www.google.com/', :body => File.dirname(__FILE__) + '/fixtures/test_txt_file') | ||
470 | + response = Net::HTTP.start('www.google.com') { |query| query.get('/') } | ||
471 | + assert response.body.split(/\n/).size == 3, "response has #{response.body.split(/\n/).size} lines should have 3" | ||
472 | + end | ||
473 | + | ||
474 | + def test_requiring_fakeweb_instead_of_fake_web | ||
475 | + require "fakeweb" | ||
476 | + end | ||
477 | + | ||
478 | + def test_registering_with_string_containing_null_byte | ||
479 | + # Regression test for File.exists? raising an ArgumentError ("string | ||
480 | + # contains null byte") since :response first tries to find by filename. | ||
481 | + # The string should be treated as a response body, instead, and an | ||
482 | + # EOFError is raised when the byte is encountered. | ||
483 | + FakeWeb.register_uri(:get, "http://example.com", :response => "test\0test") | ||
484 | + assert_raise EOFError do | ||
485 | + Net::HTTP.get(URI.parse("http://example.com")) | ||
486 | + end | ||
487 | + | ||
488 | + FakeWeb.register_uri(:get, "http://example.com", :body => "test\0test") | ||
489 | + body = Net::HTTP.get(URI.parse("http://example.com")) | ||
490 | + assert_equal "test\0test", body | ||
491 | + end | ||
492 | + | ||
493 | + def test_registering_with_string_that_is_a_directory_name | ||
494 | + # Similar to above, but for Errno::EISDIR being raised since File.exists? | ||
495 | + # returns true for directories | ||
496 | + FakeWeb.register_uri(:get, "http://example.com", :response => File.dirname(__FILE__)) | ||
497 | + assert_raise EOFError do | ||
498 | + body = Net::HTTP.get(URI.parse("http://example.com")) | ||
499 | + end | ||
500 | + | ||
501 | + FakeWeb.register_uri(:get, "http://example.com", :body => File.dirname(__FILE__)) | ||
502 | + body = Net::HTTP.get(URI.parse("http://example.com")) | ||
503 | + assert_equal File.dirname(__FILE__), body | ||
504 | + end | ||
505 | + | ||
506 | + def test_http_version_from_string_response | ||
507 | + FakeWeb.register_uri(:get, "http://example.com", :body => "example") | ||
508 | + response = Net::HTTP.start("example.com") { |http| http.get("/") } | ||
509 | + assert_equal "1.0", response.http_version | ||
510 | + end | ||
511 | + | ||
512 | + def test_http_version_from_file_response | ||
513 | + FakeWeb.register_uri(:get, "http://example.com", :body => File.dirname(__FILE__) + '/fixtures/test_example.txt') | ||
514 | + response = Net::HTTP.start("example.com") { |http| http.get("/") } | ||
515 | + assert_equal "1.0", response.http_version | ||
516 | + end | ||
517 | + | ||
518 | +end |
vendor/gems/fakeweb-1.2.5/test/test_fake_web_open_uri.rb
0 → 100644
@@ -0,0 +1,58 @@ | @@ -0,0 +1,58 @@ | ||
1 | +require File.join(File.dirname(__FILE__), "test_helper") | ||
2 | + | ||
3 | +class TestFakeWebOpenURI < Test::Unit::TestCase | ||
4 | + | ||
5 | + def test_content_for_registered_uri | ||
6 | + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => File.dirname(__FILE__) + '/fixtures/test_example.txt') | ||
7 | + assert_equal 'test example content', FakeWeb.response_for(:get, 'http://mock/test_example.txt').body | ||
8 | + end | ||
9 | + | ||
10 | + def test_mock_open | ||
11 | + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => File.dirname(__FILE__) + '/fixtures/test_example.txt') | ||
12 | + assert_equal 'test example content', open('http://mock/test_example.txt').read | ||
13 | + end | ||
14 | + | ||
15 | + def test_mock_open_with_string_as_registered_uri | ||
16 | + FakeWeb.register_uri(:get, 'http://mock/test_string.txt', :body => 'foo') | ||
17 | + assert_equal 'foo', open('http://mock/test_string.txt').string | ||
18 | + end | ||
19 | + | ||
20 | + def test_real_open | ||
21 | + FakeWeb.allow_net_connect = true | ||
22 | + setup_expectations_for_real_apple_hot_news_request | ||
23 | + resp = open('http://images.apple.com/main/rss/hotnews/hotnews.rss') | ||
24 | + assert_equal "200", resp.status.first | ||
25 | + body = resp.read | ||
26 | + assert body.include?('Apple') | ||
27 | + assert body.include?('News') | ||
28 | + end | ||
29 | + | ||
30 | + def test_mock_open_that_raises_exception | ||
31 | + FakeWeb.register_uri(:get, 'http://mock/raising_exception.txt', :exception => StandardError) | ||
32 | + assert_raises(StandardError) do | ||
33 | + open('http://mock/raising_exception.txt') | ||
34 | + end | ||
35 | + end | ||
36 | + | ||
37 | + def test_mock_open_that_raises_an_http_error | ||
38 | + FakeWeb.register_uri(:get, 'http://mock/raising_exception.txt', :exception => OpenURI::HTTPError) | ||
39 | + assert_raises(OpenURI::HTTPError) do | ||
40 | + open('http://mock/raising_exception.txt') | ||
41 | + end | ||
42 | + end | ||
43 | + | ||
44 | + def test_mock_open_that_raises_an_http_error_with_a_specific_status | ||
45 | + FakeWeb.register_uri(:get, 'http://mock/raising_exception.txt', :exception => OpenURI::HTTPError, :status => ['123', 'jodel']) | ||
46 | + exception = assert_raises(OpenURI::HTTPError) do | ||
47 | + open('http://mock/raising_exception.txt') | ||
48 | + end | ||
49 | + assert_equal '123', exception.io.code | ||
50 | + assert_equal 'jodel', exception.io.message | ||
51 | + end | ||
52 | + | ||
53 | + def test_mock_open_with_block | ||
54 | + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => File.dirname(__FILE__) + '/fixtures/test_example.txt') | ||
55 | + body = open('http://mock/test_example.txt') { |f| f.readlines } | ||
56 | + assert_equal 'test example content', body.first | ||
57 | + end | ||
58 | +end |
@@ -0,0 +1,74 @@ | @@ -0,0 +1,74 @@ | ||
1 | +$:.unshift "#{File.dirname(__FILE__)}/../lib" | ||
2 | + | ||
3 | +require 'test/unit' | ||
4 | +require 'open-uri' | ||
5 | +require 'fake_web' | ||
6 | +require 'rubygems' | ||
7 | +require 'mocha' | ||
8 | + | ||
9 | + | ||
10 | +# Give all tests a common setup and teardown that prevents shared state | ||
11 | +class Test::Unit::TestCase | ||
12 | + def setup | ||
13 | + FakeWeb.clean_registry | ||
14 | + @original_allow_net_connect = FakeWeb.allow_net_connect? | ||
15 | + FakeWeb.allow_net_connect = false | ||
16 | + end | ||
17 | + | ||
18 | + def teardown | ||
19 | + FakeWeb.allow_net_connect = @original_allow_net_connect | ||
20 | + end | ||
21 | +end | ||
22 | + | ||
23 | + | ||
24 | +module FakeWebTestHelper | ||
25 | + | ||
26 | + def capture_stderr | ||
27 | + $stderr = StringIO.new | ||
28 | + yield | ||
29 | + $stderr.rewind && $stderr.read | ||
30 | + ensure | ||
31 | + $stderr = STDERR | ||
32 | + end | ||
33 | + | ||
34 | + # Sets several expectations (using Mocha) that a real HTTP request makes it | ||
35 | + # past FakeWeb to the socket layer. You can use this when you need to check | ||
36 | + # that a request isn't handled by FakeWeb. | ||
37 | + def setup_expectations_for_real_request(options = {}) | ||
38 | + # Socket handling | ||
39 | + if options[:port] == 443 | ||
40 | + socket = mock("SSLSocket") | ||
41 | + OpenSSL::SSL::SSLSocket.expects(:===).with(socket).returns(true).at_least_once | ||
42 | + OpenSSL::SSL::SSLSocket.expects(:new).with(socket, instance_of(OpenSSL::SSL::SSLContext)).returns(socket).at_least_once | ||
43 | + socket.stubs(:sync_close=).returns(true) | ||
44 | + socket.expects(:connect).with().at_least_once | ||
45 | + else | ||
46 | + socket = mock("TCPSocket") | ||
47 | + Socket.expects(:===).with(socket).returns(true) | ||
48 | + end | ||
49 | + | ||
50 | + TCPSocket.expects(:open).with(options[:host], options[:port]).returns(socket).at_least_once | ||
51 | + socket.stubs(:closed?).returns(false) | ||
52 | + socket.stubs(:close).returns(true) | ||
53 | + | ||
54 | + # Request/response handling | ||
55 | + request_parts = ["#{options[:method]} #{options[:path]} HTTP/1.1", "Host: #{options[:host]}"] | ||
56 | + socket.expects(:write).with(all_of(includes(request_parts[0]), includes(request_parts[1]))).returns(100) | ||
57 | + | ||
58 | + socket.expects(:sysread).at_least_once.returns("HTTP/1.1 #{options[:response_code]} #{options[:response_message]}\nContent-Length: #{options[:response_body].length}\n\n#{options[:response_body]}").then.raises(EOFError) | ||
59 | + end | ||
60 | + | ||
61 | + | ||
62 | + # A helper that calls #setup_expectations_for_real_request for you, using | ||
63 | + # defaults for our commonly used test request to images.apple.com. | ||
64 | + def setup_expectations_for_real_apple_hot_news_request(options = {}) | ||
65 | + defaults = { :host => "images.apple.com", :port => 80, :method => "GET", | ||
66 | + :path => "/main/rss/hotnews/hotnews.rss", | ||
67 | + :response_code => 200, :response_message => "OK", | ||
68 | + :response_body => "<title>Apple Hot News</title>" } | ||
69 | + setup_expectations_for_real_request(defaults.merge(options)) | ||
70 | + end | ||
71 | + | ||
72 | +end | ||
73 | + | ||
74 | +Test::Unit::TestCase.send(:include, FakeWebTestHelper) |
@@ -0,0 +1,25 @@ | @@ -0,0 +1,25 @@ | ||
1 | +require File.join(File.dirname(__FILE__), "test_helper") | ||
2 | + | ||
3 | +class TestMissingOpenURI < Test::Unit::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + super | ||
7 | + @saved_open_uri = OpenURI | ||
8 | + Object.send(:remove_const, :OpenURI) | ||
9 | + end | ||
10 | + | ||
11 | + def teardown | ||
12 | + super | ||
13 | + Object.const_set(:OpenURI, @saved_open_uri) | ||
14 | + end | ||
15 | + | ||
16 | + | ||
17 | + def test_register_using_exception_without_open_uri | ||
18 | + # regression test for Responder needing OpenURI::HTTPError to be defined | ||
19 | + FakeWeb.register_uri(:get, "http://example.com/", :exception => StandardError) | ||
20 | + assert_raises(StandardError) do | ||
21 | + Net::HTTP.start("example.com") { |http| http.get("/") } | ||
22 | + end | ||
23 | + end | ||
24 | + | ||
25 | +end |
@@ -0,0 +1,51 @@ | @@ -0,0 +1,51 @@ | ||
1 | +require File.join(File.dirname(__FILE__), "test_helper") | ||
2 | + | ||
3 | +class TestPrecedence < Test::Unit::TestCase | ||
4 | + | ||
5 | + def test_matching_get_strings_have_precedence_over_matching_get_regexes | ||
6 | + FakeWeb.register_uri(:get, "http://example.com/test", :body => "string") | ||
7 | + FakeWeb.register_uri(:get, %r|http://example\.com/test|, :body => "regex") | ||
8 | + response = Net::HTTP.start("example.com") { |query| query.get('/test') } | ||
9 | + assert_equal "string", response.body | ||
10 | + end | ||
11 | + | ||
12 | + def test_matching_any_strings_have_precedence_over_matching_any_regexes | ||
13 | + FakeWeb.register_uri(:any, "http://example.com/test", :body => "string") | ||
14 | + FakeWeb.register_uri(:any, %r|http://example\.com/test|, :body => "regex") | ||
15 | + response = Net::HTTP.start("example.com") { |query| query.get('/test') } | ||
16 | + assert_equal "string", response.body | ||
17 | + end | ||
18 | + | ||
19 | + def test_matching_get_strings_have_precedence_over_matching_any_strings | ||
20 | + FakeWeb.register_uri(:get, "http://example.com/test", :body => "get method") | ||
21 | + FakeWeb.register_uri(:any, "http://example.com/test", :body => "any method") | ||
22 | + response = Net::HTTP.start("example.com") { |query| query.get('/test') } | ||
23 | + assert_equal "get method", response.body | ||
24 | + | ||
25 | + # registration order should not matter | ||
26 | + FakeWeb.register_uri(:any, "http://example.com/test2", :body => "any method") | ||
27 | + FakeWeb.register_uri(:get, "http://example.com/test2", :body => "get method") | ||
28 | + response = Net::HTTP.start("example.com") { |query| query.get('/test2') } | ||
29 | + assert_equal "get method", response.body | ||
30 | + end | ||
31 | + | ||
32 | + def test_matching_any_strings_have_precedence_over_matching_get_regexes | ||
33 | + FakeWeb.register_uri(:any, "http://example.com/test", :body => "any string") | ||
34 | + FakeWeb.register_uri(:get, %r|http://example\.com/test|, :body => "get regex") | ||
35 | + response = Net::HTTP.start("example.com") { |query| query.get('/test') } | ||
36 | + assert_equal "any string", response.body | ||
37 | + end | ||
38 | + | ||
39 | + def test_registered_strings_and_uris_are_equivalent_so_second_takes_precedence | ||
40 | + FakeWeb.register_uri(:get, "http://example.com/test", :body => "string") | ||
41 | + FakeWeb.register_uri(:get, URI.parse("http://example.com/test"), :body => "uri") | ||
42 | + response = Net::HTTP.start("example.com") { |query| query.get('/test') } | ||
43 | + assert_equal "uri", response.body | ||
44 | + | ||
45 | + FakeWeb.register_uri(:get, URI.parse("http://example.com/test2"), :body => "uri") | ||
46 | + FakeWeb.register_uri(:get, "http://example.com/test2", :body => "string") | ||
47 | + response = Net::HTTP.start("example.com") { |query| query.get('/test2') } | ||
48 | + assert_equal "string", response.body | ||
49 | + end | ||
50 | + | ||
51 | +end |
@@ -0,0 +1,45 @@ | @@ -0,0 +1,45 @@ | ||
1 | +require File.join(File.dirname(__FILE__), "test_helper") | ||
2 | + | ||
3 | +class TestFakeWebQueryString < Test::Unit::TestCase | ||
4 | + | ||
5 | + def test_register_uri_string_with_query_params | ||
6 | + FakeWeb.register_uri(:get, 'http://example.com/?a=1&b=1', :body => 'foo') | ||
7 | + assert FakeWeb.registered_uri?(:get, 'http://example.com/?a=1&b=1') | ||
8 | + | ||
9 | + FakeWeb.register_uri(:post, URI.parse("http://example.org/?a=1&b=1"), :body => "foo") | ||
10 | + assert FakeWeb.registered_uri?(:post, "http://example.org/?a=1&b=1") | ||
11 | + end | ||
12 | + | ||
13 | + def test_register_uri_with_query_params_and_check_in_different_order | ||
14 | + FakeWeb.register_uri(:get, 'http://example.com/?a=1&b=1', :body => 'foo') | ||
15 | + assert FakeWeb.registered_uri?(:get, 'http://example.com/?b=1&a=1') | ||
16 | + | ||
17 | + FakeWeb.register_uri(:post, URI.parse('http://example.org/?a=1&b=1'), :body => 'foo') | ||
18 | + assert FakeWeb.registered_uri?(:post, 'http://example.org/?b=1&a=1') | ||
19 | + end | ||
20 | + | ||
21 | + def test_registered_uri_gets_recognized_with_empty_query_params | ||
22 | + FakeWeb.register_uri(:get, 'http://example.com/', :body => 'foo') | ||
23 | + assert FakeWeb.registered_uri?(:get, 'http://example.com/?') | ||
24 | + | ||
25 | + FakeWeb.register_uri(:post, URI.parse('http://example.org/'), :body => 'foo') | ||
26 | + assert FakeWeb.registered_uri?(:post, 'http://example.org/?') | ||
27 | + end | ||
28 | + | ||
29 | + def test_register_uri_with_empty_query_params_and_check_with_none | ||
30 | + FakeWeb.register_uri(:get, 'http://example.com/?', :body => 'foo') | ||
31 | + assert FakeWeb.registered_uri?(:get, 'http://example.com/') | ||
32 | + | ||
33 | + FakeWeb.register_uri(:post, URI.parse('http://example.org/?'), :body => 'foo') | ||
34 | + assert FakeWeb.registered_uri?(:post, 'http://example.org/') | ||
35 | + end | ||
36 | + | ||
37 | + def test_registry_sort_query_params | ||
38 | + assert_equal "a=1&b=2", FakeWeb::Registry.instance.send(:sort_query_params, "b=2&a=1") | ||
39 | + end | ||
40 | + | ||
41 | + def test_registry_sort_query_params_sorts_by_value_if_keys_collide | ||
42 | + assert_equal "a=1&a=2&b=2", FakeWeb::Registry.instance.send(:sort_query_params, "a=2&b=2&a=1") | ||
43 | + end | ||
44 | + | ||
45 | +end |
@@ -0,0 +1,103 @@ | @@ -0,0 +1,103 @@ | ||
1 | +require File.join(File.dirname(__FILE__), "test_helper") | ||
2 | + | ||
3 | +class TestRegexes < Test::Unit::TestCase | ||
4 | + | ||
5 | + def test_registered_uri_with_pattern | ||
6 | + FakeWeb.register_uri(:get, %r|http://example.com/test_example/\d+|, :body => "example") | ||
7 | + assert FakeWeb.registered_uri?(:get, "http://example.com/test_example/25") | ||
8 | + assert !FakeWeb.registered_uri?(:get, "http://example.com/test_example/abc") | ||
9 | + end | ||
10 | + | ||
11 | + def test_response_for_with_matching_registered_uri | ||
12 | + FakeWeb.register_uri(:get, %r|http://www.google.com|, :body => "Welcome to Google!") | ||
13 | + assert_equal "Welcome to Google!", FakeWeb.response_for(:get, "http://www.google.com").body | ||
14 | + end | ||
15 | + | ||
16 | + def test_response_for_with_matching_registered_uri_and_get_method_matching_to_any_method | ||
17 | + FakeWeb.register_uri(:any, %r|http://www.example.com|, :body => "example") | ||
18 | + assert_equal "example", FakeWeb.response_for(:get, "http://www.example.com").body | ||
19 | + end | ||
20 | + | ||
21 | + def test_registered_uri_with_authentication_and_pattern | ||
22 | + FakeWeb.register_uri(:get, %r|http://user:pass@mock/example\.\w+|i, :body => "example") | ||
23 | + assert FakeWeb.registered_uri?(:get, 'http://user:pass@mock/example.txt') | ||
24 | + end | ||
25 | + | ||
26 | + def test_registered_uri_with_authentication_and_pattern_handles_case_insensitivity | ||
27 | + FakeWeb.register_uri(:get, %r|http://user:pass@mock/example\.\w+|i, :body => "example") | ||
28 | + assert FakeWeb.registered_uri?(:get, 'http://uSeR:PAss@mock/example.txt') | ||
29 | + end | ||
30 | + | ||
31 | + def test_request_with_authentication_and_pattern_handles_case_insensitivity | ||
32 | + FakeWeb.register_uri(:get, %r|http://user:pass@mock/example\.\w+|i, :body => "example") | ||
33 | + http = Net::HTTP.new('mock', 80) | ||
34 | + req = Net::HTTP::Get.new('/example.txt') | ||
35 | + req.basic_auth 'uSeR', 'PAss' | ||
36 | + assert_equal "example", http.request(req).body | ||
37 | + end | ||
38 | + | ||
39 | + def test_requesting_a_uri_that_matches_two_registered_regexes_raises_an_error | ||
40 | + FakeWeb.register_uri(:get, %r|http://example\.com/|, :body => "first") | ||
41 | + FakeWeb.register_uri(:get, %r|http://example\.com/a|, :body => "second") | ||
42 | + assert_raise FakeWeb::MultipleMatchingRegexpsError do | ||
43 | + Net::HTTP.start("example.com") { |query| query.get('/a') } | ||
44 | + end | ||
45 | + end | ||
46 | + | ||
47 | + def test_requesting_a_uri_that_matches_two_registered_regexes_raises_an_error_including_request_info | ||
48 | + FakeWeb.register_uri(:get, %r|http://example\.com/|, :body => "first") | ||
49 | + FakeWeb.register_uri(:get, %r|http://example\.com/a|, :body => "second") | ||
50 | + begin | ||
51 | + Net::HTTP.start("example.com") { |query| query.get('/a') } | ||
52 | + rescue FakeWeb::MultipleMatchingRegexpsError => exception | ||
53 | + end | ||
54 | + assert exception.message.include?("GET http://example.com/a") | ||
55 | + end | ||
56 | + | ||
57 | + def test_registry_does_not_find_using_mismatched_protocols_or_ports_when_registered_with_both | ||
58 | + FakeWeb.register_uri(:get, %r|http://www.example.com:80|, :body => "example") | ||
59 | + assert !FakeWeb.registered_uri?(:get, "https://www.example.com:80") | ||
60 | + assert !FakeWeb.registered_uri?(:get, "http://www.example.com:443") | ||
61 | + end | ||
62 | + | ||
63 | + def test_registry_only_finds_using_default_port_when_registered_without_if_protocol_matches | ||
64 | + FakeWeb.register_uri(:get, %r|http://www.example.com/test|, :body => "example") | ||
65 | + assert FakeWeb.registered_uri?(:get, "http://www.example.com:80/test") | ||
66 | + assert !FakeWeb.registered_uri?(:get, "http://www.example.com:443/test") | ||
67 | + assert !FakeWeb.registered_uri?(:get, "https://www.example.com:443/test") | ||
68 | + FakeWeb.register_uri(:get, %r|https://www.example.org/test|, :body => "example") | ||
69 | + assert FakeWeb.registered_uri?(:get, "https://www.example.org:443/test") | ||
70 | + assert !FakeWeb.registered_uri?(:get, "https://www.example.org:80/test") | ||
71 | + assert !FakeWeb.registered_uri?(:get, "http://www.example.org:80/test") | ||
72 | + end | ||
73 | + | ||
74 | + def test_registry_matches_using_mismatched_port_when_registered_without | ||
75 | + FakeWeb.register_uri(:get, %r|http://www.example.com|, :body => "example") | ||
76 | + assert FakeWeb.registered_uri?(:get, "http://www.example.com:80") | ||
77 | + assert FakeWeb.registered_uri?(:get, "http://www.example.com:443") | ||
78 | + assert FakeWeb.registered_uri?(:get, "http://www.example.com:12345") | ||
79 | + assert !FakeWeb.registered_uri?(:get, "https://www.example.com:443") | ||
80 | + assert !FakeWeb.registered_uri?(:get, "https://www.example.com") | ||
81 | + end | ||
82 | + | ||
83 | + def test_registry_matches_using_any_protocol_and_port_when_registered_without_protocol_or_port | ||
84 | + FakeWeb.register_uri(:get, %r|www.example.com|, :body => "example") | ||
85 | + assert FakeWeb.registered_uri?(:get, "http://www.example.com") | ||
86 | + assert FakeWeb.registered_uri?(:get, "http://www.example.com:80") | ||
87 | + assert FakeWeb.registered_uri?(:get, "http://www.example.com:443") | ||
88 | + assert FakeWeb.registered_uri?(:get, "https://www.example.com") | ||
89 | + assert FakeWeb.registered_uri?(:get, "https://www.example.com:80") | ||
90 | + assert FakeWeb.registered_uri?(:get, "https://www.example.com:443") | ||
91 | + end | ||
92 | + | ||
93 | + def test_registry_matches_with_query_params | ||
94 | + FakeWeb.register_uri(:get, %r[example.com/list\?(.*&|)important=1], :body => "example") | ||
95 | + assert FakeWeb.registered_uri?(:get, "http://example.com/list?hash=123&important=1&unimportant=2") | ||
96 | + assert FakeWeb.registered_uri?(:get, "http://example.com/list?hash=123&important=12&unimportant=2") | ||
97 | + assert FakeWeb.registered_uri?(:get, "http://example.com/list?important=1&unimportant=2") | ||
98 | + assert !FakeWeb.registered_uri?(:get, "http://example.com/list?important=2") | ||
99 | + assert !FakeWeb.registered_uri?(:get, "http://example.com/list?important=2&unimportant=1") | ||
100 | + assert !FakeWeb.registered_uri?(:get, "http://example.com/list?hash=123&important=2&unimportant=1") | ||
101 | + assert !FakeWeb.registered_uri?(:get, "http://example.com/list?notimportant=1&unimportant=1") | ||
102 | + end | ||
103 | +end |
@@ -0,0 +1,67 @@ | @@ -0,0 +1,67 @@ | ||
1 | +require File.join(File.dirname(__FILE__), "test_helper") | ||
2 | + | ||
3 | +class TestResponseHeaders < Test::Unit::TestCase | ||
4 | + | ||
5 | + def test_content_type_when_registering_with_string_and_content_type_header | ||
6 | + FakeWeb.register_uri(:get, "http://example.com/users.json", :body => '[{"username": "chrisk"}]', :content_type => "application/json") | ||
7 | + response = Net::HTTP.start("example.com") { |query| query.get("/users.json") } | ||
8 | + assert_equal '[{"username": "chrisk"}]', response.body | ||
9 | + assert_equal "application/json", response['Content-Type'] | ||
10 | + end | ||
11 | + | ||
12 | + def test_content_type_when_registering_with_string_only | ||
13 | + FakeWeb.register_uri(:get, "http://example.com/users.json", :body => '[{"username": "chrisk"}]') | ||
14 | + response = Net::HTTP.start("example.com") { |query| query.get("/users.json") } | ||
15 | + assert_equal '[{"username": "chrisk"}]', response.body | ||
16 | + assert_nil response['Content-Type'] | ||
17 | + end | ||
18 | + | ||
19 | + def test_cookies_when_registering_with_file_and_set_cookie_header | ||
20 | + FakeWeb.register_uri(:get, "http://example.com/", :body => File.dirname(__FILE__) + '/fixtures/test_example.txt', | ||
21 | + :set_cookie => "user_id=1; example=yes") | ||
22 | + response = Net::HTTP.start("example.com") { |query| query.get("/") } | ||
23 | + assert_equal "test example content", response.body | ||
24 | + assert_equal "user_id=1; example=yes", response['Set-Cookie'] | ||
25 | + end | ||
26 | + | ||
27 | + def test_registering_with_baked_response_ignores_header_options | ||
28 | + fake_response = Net::HTTPOK.new('1.1', '200', 'OK') | ||
29 | + fake_response["Server"] = "Apache/1.3.27 (Unix)" | ||
30 | + FakeWeb.register_uri(:get, "http://example.com/", :response => fake_response, | ||
31 | + :server => "FakeWeb/1.2.3 (Ruby)") | ||
32 | + response = Net::HTTP.start("example.com") { |query| query.get("/") } | ||
33 | + assert_equal "200", response.code | ||
34 | + assert_equal "OK", response.message | ||
35 | + assert_equal "Apache/1.3.27 (Unix)", response["Server"] | ||
36 | + end | ||
37 | + | ||
38 | + def test_headers_are_rotated_when_registering_with_response_rotation | ||
39 | + FakeWeb.register_uri(:get, "http://example.com", | ||
40 | + [{:body => 'test1', :expires => "Thu, 14 Jun 2009 16:00:00 GMT", | ||
41 | + :content_type => "text/plain"}, | ||
42 | + {:body => 'test2', :expires => "Thu, 14 Jun 2009 16:00:01 GMT"}]) | ||
43 | + | ||
44 | + first_response = second_response = nil | ||
45 | + Net::HTTP.start("example.com") do |query| | ||
46 | + first_response = query.get("/") | ||
47 | + second_response = query.get("/") | ||
48 | + end | ||
49 | + assert_equal 'test1', first_response.body | ||
50 | + assert_equal "Thu, 14 Jun 2009 16:00:00 GMT", first_response['Expires'] | ||
51 | + assert_equal "text/plain", first_response['Content-Type'] | ||
52 | + assert_equal 'test2', second_response.body | ||
53 | + assert_equal "Thu, 14 Jun 2009 16:00:01 GMT", second_response['Expires'] | ||
54 | + assert_nil second_response['Content-Type'] | ||
55 | + end | ||
56 | + | ||
57 | + def test_registering_with_status_option_and_response_headers | ||
58 | + FakeWeb.register_uri(:get, "http://example.com", :status => ["301", "Moved Permanently"], | ||
59 | + :location => "http://www.example.com") | ||
60 | + | ||
61 | + response = Net::HTTP.start("example.com") { |query| query.get("/") } | ||
62 | + assert_equal "301", response.code | ||
63 | + assert_equal "Moved Permanently", response.message | ||
64 | + assert_equal "http://www.example.com", response["Location"] | ||
65 | + end | ||
66 | + | ||
67 | +end |
@@ -0,0 +1,53 @@ | @@ -0,0 +1,53 @@ | ||
1 | +require File.join(File.dirname(__FILE__), "test_helper") | ||
2 | + | ||
3 | +class TestFakeWebTrailingSlashes < Test::Unit::TestCase | ||
4 | + | ||
5 | + def test_registering_root_without_slash_and_ask_predicate_method_with_slash | ||
6 | + FakeWeb.register_uri(:get, "http://www.example.com", :body => "root") | ||
7 | + assert FakeWeb.registered_uri?(:get, "http://www.example.com/") | ||
8 | + end | ||
9 | + | ||
10 | + def test_registering_root_without_slash_and_request | ||
11 | + FakeWeb.register_uri(:get, "http://www.example.com", :body => "root") | ||
12 | + response = Net::HTTP.start("www.example.com") { |query| query.get('/') } | ||
13 | + assert_equal "root", response.body | ||
14 | + end | ||
15 | + | ||
16 | + def test_registering_root_with_slash_and_ask_predicate_method_without_slash | ||
17 | + FakeWeb.register_uri(:get, "http://www.example.com/", :body => "root") | ||
18 | + assert FakeWeb.registered_uri?(:get, "http://www.example.com") | ||
19 | + end | ||
20 | + | ||
21 | + def test_registering_root_with_slash_and_request | ||
22 | + FakeWeb.register_uri(:get, "http://www.example.com/", :body => "root") | ||
23 | + response = Net::HTTP.start("www.example.com") { |query| query.get('/') } | ||
24 | + assert_equal "root", response.body | ||
25 | + end | ||
26 | + | ||
27 | + def test_registering_path_without_slash_and_ask_predicate_method_with_slash | ||
28 | + FakeWeb.register_uri(:get, "http://www.example.com/users", :body => "User list") | ||
29 | + assert !FakeWeb.registered_uri?(:get, "http://www.example.com/users/") | ||
30 | + end | ||
31 | + | ||
32 | + def test_registering_path_without_slash_and_request_with_slash | ||
33 | + FakeWeb.allow_net_connect = false | ||
34 | + FakeWeb.register_uri(:get, "http://www.example.com/users", :body => "User list") | ||
35 | + assert_raise FakeWeb::NetConnectNotAllowedError do | ||
36 | + response = Net::HTTP.start("www.example.com") { |query| query.get('/users/') } | ||
37 | + end | ||
38 | + end | ||
39 | + | ||
40 | + def test_registering_path_with_slash_and_ask_predicate_method_without_slash | ||
41 | + FakeWeb.register_uri(:get, "http://www.example.com/users/", :body => "User list") | ||
42 | + assert !FakeWeb.registered_uri?(:get, "http://www.example.com/users") | ||
43 | + end | ||
44 | + | ||
45 | + def test_registering_path_with_slash_and_request_without_slash | ||
46 | + FakeWeb.allow_net_connect = false | ||
47 | + FakeWeb.register_uri(:get, "http://www.example.com/users/", :body => "User list") | ||
48 | + assert_raise FakeWeb::NetConnectNotAllowedError do | ||
49 | + response = Net::HTTP.start("www.example.com") { |query| query.get('/users') } | ||
50 | + end | ||
51 | + end | ||
52 | + | ||
53 | +end |
@@ -0,0 +1,70 @@ | @@ -0,0 +1,70 @@ | ||
1 | +require File.join(File.dirname(__FILE__), "test_helper") | ||
2 | + | ||
3 | +class TestUtility < Test::Unit::TestCase | ||
4 | + | ||
5 | + def test_decode_userinfo_from_header_handles_basic_auth | ||
6 | + authorization_header = "Basic dXNlcm5hbWU6c2VjcmV0" | ||
7 | + userinfo = FakeWeb::Utility.decode_userinfo_from_header(authorization_header) | ||
8 | + assert_equal "username:secret", userinfo | ||
9 | + end | ||
10 | + | ||
11 | + def test_encode_unsafe_chars_in_userinfo_does_not_encode_userinfo_safe_punctuation | ||
12 | + userinfo = "user;&=+$,:secret" | ||
13 | + assert_equal userinfo, FakeWeb::Utility.encode_unsafe_chars_in_userinfo(userinfo) | ||
14 | + end | ||
15 | + | ||
16 | + def test_encode_unsafe_chars_in_userinfo_does_not_encode_rfc_3986_unreserved_characters | ||
17 | + userinfo = "-_.!~*'()abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:secret" | ||
18 | + assert_equal userinfo, FakeWeb::Utility.encode_unsafe_chars_in_userinfo(userinfo) | ||
19 | + end | ||
20 | + | ||
21 | + def test_encode_unsafe_chars_in_userinfo_does_encode_other_characters | ||
22 | + userinfo, safe_userinfo = 'us#rn@me:sec//ret?"', 'us%23rn%40me:sec%2F%2Fret%3F%22' | ||
23 | + assert_equal safe_userinfo, FakeWeb::Utility.encode_unsafe_chars_in_userinfo(userinfo) | ||
24 | + end | ||
25 | + | ||
26 | + def test_strip_default_port_from_uri_strips_80_from_http_with_path | ||
27 | + uri = "http://example.com:80/foo/bar" | ||
28 | + stripped_uri = FakeWeb::Utility.strip_default_port_from_uri(uri) | ||
29 | + assert_equal "http://example.com/foo/bar", stripped_uri | ||
30 | + end | ||
31 | + | ||
32 | + def test_strip_default_port_from_uri_strips_80_from_http_without_path | ||
33 | + uri = "http://example.com:80" | ||
34 | + stripped_uri = FakeWeb::Utility.strip_default_port_from_uri(uri) | ||
35 | + assert_equal "http://example.com", stripped_uri | ||
36 | + end | ||
37 | + | ||
38 | + def test_strip_default_port_from_uri_strips_443_from_https_without_path | ||
39 | + uri = "https://example.com:443" | ||
40 | + stripped_uri = FakeWeb::Utility.strip_default_port_from_uri(uri) | ||
41 | + assert_equal "https://example.com", stripped_uri | ||
42 | + end | ||
43 | + | ||
44 | + def test_strip_default_port_from_uri_strips_443_from_https | ||
45 | + uri = "https://example.com:443/foo/bar" | ||
46 | + stripped_uri = FakeWeb::Utility.strip_default_port_from_uri(uri) | ||
47 | + assert_equal "https://example.com/foo/bar", stripped_uri | ||
48 | + end | ||
49 | + | ||
50 | + def test_strip_default_port_from_uri_does_not_strip_8080_from_http | ||
51 | + uri = "http://example.com:8080/foo/bar" | ||
52 | + assert_equal uri, FakeWeb::Utility.strip_default_port_from_uri(uri) | ||
53 | + end | ||
54 | + | ||
55 | + def test_strip_default_port_from_uri_does_not_strip_443_from_http | ||
56 | + uri = "http://example.com:443/foo/bar" | ||
57 | + assert_equal uri, FakeWeb::Utility.strip_default_port_from_uri(uri) | ||
58 | + end | ||
59 | + | ||
60 | + def test_strip_default_port_from_uri_does_not_strip_80_from_query_string | ||
61 | + uri = "http://example.com/?a=:80&b=c" | ||
62 | + assert_equal uri, FakeWeb::Utility.strip_default_port_from_uri(uri) | ||
63 | + end | ||
64 | + | ||
65 | + def test_strip_default_port_from_uri_does_not_modify_strings_that_do_not_start_with_http_or_https | ||
66 | + uri = "httpz://example.com:80/" | ||
67 | + assert_equal uri, FakeWeb::Utility.strip_default_port_from_uri(uri) | ||
68 | + end | ||
69 | + | ||
70 | +end |
@@ -0,0 +1,35 @@ | @@ -0,0 +1,35 @@ | ||
1 | +=== 0.2.0 / 2008-12-23 | ||
2 | + | ||
3 | +* API Changes | ||
4 | + | ||
5 | + * Timecop#travel no longer freezes time. Rather, it computes the current offset between the new "now" and the real "now", and | ||
6 | + returns times as if Time had continued to move forward | ||
7 | + | ||
8 | + * Timecop#freeze now behaves exactly as the old Timecop#travel behaved. Unless you depended on the actual freezing of time | ||
9 | + (which I think would be rare), you should be able to continue to use #travel without worry. | ||
10 | + | ||
11 | + * Timecop#return is now exposed (previously Timecop#unset_all, but not well advertised). It will completely unmock time, | ||
12 | + and will probably be rarely used outside of the actual implementation of this library. | ||
13 | + | ||
14 | +* More Test Coverage | ||
15 | + | ||
16 | + * Tests now explicitly cover the cases when the Date and DateTime objects are not loaded, and ensures proper functionality | ||
17 | + in their absence and existence. | ||
18 | + | ||
19 | + * Still haven't done regression testing against anything other than a few version of 1.8.6 (including REE). We should | ||
20 | + probably try to get this tested on both 1.8.7 and 1.9.1. | ||
21 | + | ||
22 | +* Documentation | ||
23 | + | ||
24 | + * Fixed up a lot of the poorly-formatted rdoc syntax. The public API should now be properly published in the rdoc, | ||
25 | + and the internals are omitted. | ||
26 | + | ||
27 | +=== 0.1.0 / 2008-11-09 | ||
28 | + | ||
29 | +* Initial Feature Set | ||
30 | + | ||
31 | + * Temporarily (or permanently if you prefer) change the concept of Time.now, DateTime.now (if defined), and Date.today (if defined) | ||
32 | + * Timecop#travel api allows an argument to be passed in as one of: 1) Time instance, 2) DateTime instance, 3) Date instance, | ||
33 | + 4) individual arguments (year, month, day, hour, minute, second) | ||
34 | + * Nested calls to Timecop#travel are supported -- each block will maintain it's interpretation of now. | ||
35 | + |
@@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
1 | +History.txt | ||
2 | +Manifest.txt | ||
3 | +README.txt | ||
4 | +Rakefile | ||
5 | +lib/timecop.rb | ||
6 | +lib/timecop/stack_item.rb | ||
7 | +lib/timecop/time_extensions.rb | ||
8 | +lib/timecop/timecop.rb | ||
9 | +lib/timecop/version.rb | ||
10 | +test/run_tests.sh | ||
11 | +test/test_timecop.rb | ||
12 | +test/test_timecop_internals.rb | ||
13 | +test/test_timecop_without_date.rb | ||
14 | +timecop.gemspec |
@@ -0,0 +1,84 @@ | @@ -0,0 +1,84 @@ | ||
1 | +h1. timecop | ||
2 | + | ||
3 | +* http://github.com/jtrupiano/timecop | ||
4 | + | ||
5 | +h2. DESCRIPTION | ||
6 | + | ||
7 | +A gem providing simple ways to mock Time.now, Date.today, and DateTime.now. It provides "time travel" and "time freezing" capabilities, making it dead simple to test time-dependent code. | ||
8 | + | ||
9 | +h2. FEATURES | ||
10 | + | ||
11 | +* Temporarily (or permanently if you prefer) change the concept of Time.now, DateTime.now, and Date.today | ||
12 | +* Timecop api allows arguments to be passed into #freeze and #travel as one of the following: | ||
13 | + # Time instance | ||
14 | + # DateTime instance | ||
15 | + # Date instance | ||
16 | + # individual arguments (year, month, day, hour, minute, second) | ||
17 | + # a single integer argument that is interpreted as an offset in seconds from Time.now | ||
18 | + | ||
19 | +* Nested calls to Timecop#travel and Timecop#freeze are supported -- each block will maintain it's interpretation of now. | ||
20 | + | ||
21 | +h2. SHORTCOMINGS | ||
22 | + | ||
23 | +* Only fully tested on the 1.8.6 Ruby implementations. 1.8.7 and 1.9.1 should be tested, as well as other flavors (jruby, etc.) | ||
24 | + | ||
25 | +h2. SYNOPSIS | ||
26 | + | ||
27 | +* Run a time-sensitive test: | ||
28 | +<code> | ||
29 | + joe = User.find(1) | ||
30 | + joe.purchase_home() | ||
31 | + assert !joe.mortgage_due? | ||
32 | + # move ahead a month and assert that the mortgage is due | ||
33 | + Timecop.freeze(Date.today + 30) do | ||
34 | + assert joe.mortgage_due? | ||
35 | + end | ||
36 | +</code> | ||
37 | + | ||
38 | +* Set the time for the test environment of a rails app -- this is particularly helpful if your whole application | ||
39 | + is time-sensitive. It allows you to build your test data at a single point in time, and to move in/out of that | ||
40 | + time as appropriate (within your tests) | ||
41 | + | ||
42 | +in config/environments/test.rb | ||
43 | + | ||
44 | +<code> | ||
45 | +config.after_initialize do | ||
46 | + # Set Time.now to September 1, 2008 10:05:00 AM | ||
47 | + t = Time.local(2008, 9, 1, 10, 5, 0) | ||
48 | + Timecop.travel(t) | ||
49 | +end | ||
50 | +</code> | ||
51 | + | ||
52 | +h2. REQUIREMENTS | ||
53 | + | ||
54 | +* None | ||
55 | + | ||
56 | +h2. INSTALL | ||
57 | + | ||
58 | +* sudo gem install timecop (latest stable version from rubyforge) | ||
59 | +* sudo gem install jtrupiano-timecop (HEAD of the repo from github) | ||
60 | + | ||
61 | +h2. LICENSE | ||
62 | + | ||
63 | +(The MIT License) | ||
64 | + | ||
65 | +Copyright (c) 2008 FIX | ||
66 | + | ||
67 | +Permission is hereby granted, free of charge, to any person obtaining | ||
68 | +a copy of this software and associated documentation files (the | ||
69 | +'Software'), to deal in the Software without restriction, including | ||
70 | +without limitation the rights to use, copy, modify, merge, publish, | ||
71 | +distribute, sublicense, and/or sell copies of the Software, and to | ||
72 | +permit persons to whom the Software is furnished to do so, subject to | ||
73 | +the following conditions: | ||
74 | + | ||
75 | +The above copyright notice and this permission notice shall be | ||
76 | +included in all copies or substantial portions of the Software. | ||
77 | + | ||
78 | +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||
79 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
80 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
81 | +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
82 | +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
83 | +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
84 | +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
@@ -0,0 +1,31 @@ | @@ -0,0 +1,31 @@ | ||
1 | +require 'rake' | ||
2 | +require 'rake/testtask' | ||
3 | +require 'rake/rdoctask' | ||
4 | + | ||
5 | +begin | ||
6 | + require 'jeweler' | ||
7 | + Jeweler::Tasks.new do |s| | ||
8 | + s.name = "timecop" | ||
9 | + s.rubyforge_project = 'johntrupiano' # if different than lowercase project name | ||
10 | + s.description = %q(A gem providing simple ways to temporarily override Time.now, Date.today, and DateTime.now. It provides "time travel" capabilities, making it dead simple to test time-dependent code.) | ||
11 | + s.summary = s.description # More details later?? | ||
12 | + s.email = "jtrupiano@gmail.com" | ||
13 | + s.homepage = "http://github.com/jtrupiano/timecop" | ||
14 | + s.authors = ["John Trupiano"] | ||
15 | + s.files = FileList["[A-Z]*", "{bin,lib,test}/**/*"] | ||
16 | + #s.add_dependency 'schacon-git' | ||
17 | + end | ||
18 | +rescue LoadError | ||
19 | + puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com" | ||
20 | +end | ||
21 | + | ||
22 | +# Override the test task and instruct them how to actually run the tests. | ||
23 | +Rake.application.send(:eval, "@tasks.delete('test')") | ||
24 | +desc "Does not execute tests. Manually run shell script ./run_tests.sh to execute tests." | ||
25 | +task :test do | ||
26 | + puts <<-MSG | ||
27 | + In order to run the test suite, run: cd test && ./run_tests.sh | ||
28 | + The tests need to be run with different libraries loaded, which rules out using Rake | ||
29 | + to automate them. | ||
30 | + MSG | ||
31 | +end |
vendor/gems/jtrupiano-timecop-0.2.1/lib/timecop/stack_item.rb
0 → 100644
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | + | ||
2 | +# Simply a data class for carrying around "time movement" objects. Makes it easy to keep track of the time | ||
3 | +# movements on a simple stack. | ||
4 | +class StackItem | ||
5 | + | ||
6 | + attr_reader :mock_type, :year, :month, :day, :hour, :minute, :second | ||
7 | + def initialize(mock_type, year, month, day, hour, minute, second) | ||
8 | + @mock_type, @year, @month, @day, @hour, @minute, @second = mock_type, year, month, day, hour, minute, second | ||
9 | + end | ||
10 | +end | ||
11 | + |
vendor/gems/jtrupiano-timecop-0.2.1/lib/timecop/time_extensions.rb
0 → 100644
@@ -0,0 +1,96 @@ | @@ -0,0 +1,96 @@ | ||
1 | +# 1. Extensions to the Time, Date, and DateTime objects | ||
2 | +# 2. Allows us to "freeze" time in our Ruby applications. | ||
3 | +# 3. This is very useful when your app's functionality is dependent on time (e.g. | ||
4 | +# anything that might expire). This will allow us to alter the return value of | ||
5 | +# Date.today, Time.now, and DateTime.now, such that our application code _never_ has to change. | ||
6 | + | ||
7 | +class Time | ||
8 | + class << self | ||
9 | + # Time we might be behaving as | ||
10 | + #attr_reader :mock_time | ||
11 | + | ||
12 | + @@mock_offset = nil | ||
13 | + @@mock_time = nil | ||
14 | + | ||
15 | + def mock_time | ||
16 | + if !@@mock_offset.nil? | ||
17 | + now_without_mock_time - @@mock_offset | ||
18 | + else | ||
19 | + @@mock_time | ||
20 | + end | ||
21 | + end | ||
22 | + | ||
23 | + # Set new time to pretend we are. | ||
24 | + def freeze_time(new_now) | ||
25 | + @@mock_time = new_now | ||
26 | + @@mock_offset = nil | ||
27 | + end | ||
28 | + | ||
29 | + def move_time(new_now) | ||
30 | + @@mock_offset = new_now.nil? ? nil : (now_without_mock_time - new_now) | ||
31 | + @@mock_time = nil | ||
32 | + end | ||
33 | + | ||
34 | + # Restores Time to system clock | ||
35 | + def unmock! | ||
36 | + move_time(nil) | ||
37 | + end | ||
38 | + | ||
39 | + # Alias the original now | ||
40 | + alias_method :now_without_mock_time, :now | ||
41 | + | ||
42 | + # Define now_with_mock_time | ||
43 | + def now_with_mock_time | ||
44 | + mock_time || now_without_mock_time | ||
45 | + end | ||
46 | + | ||
47 | + # Alias now to now_with_mock_time | ||
48 | + alias_method :now, :now_with_mock_time | ||
49 | + end | ||
50 | +end | ||
51 | + | ||
52 | +if Object.const_defined?(:Date) | ||
53 | + class Date | ||
54 | + class << self | ||
55 | + def mock_date | ||
56 | + now = Time.mock_time | ||
57 | + return nil if now.nil? | ||
58 | + Date.new(now.year, now.month, now.day) | ||
59 | + end | ||
60 | + | ||
61 | + # Alias the original today | ||
62 | + alias_method :today_without_mock_date, :today | ||
63 | + | ||
64 | + # Define today_with_mock_date | ||
65 | + def today_with_mock_date | ||
66 | + mock_date || today_without_mock_date | ||
67 | + end | ||
68 | + | ||
69 | + # Alias today to today_with_mock_date | ||
70 | + alias_method :today, :today_with_mock_date | ||
71 | + end | ||
72 | + end | ||
73 | +end | ||
74 | + | ||
75 | +if Object.const_defined?(:DateTime) | ||
76 | + class DateTime | ||
77 | + class << self | ||
78 | + def mock_time | ||
79 | + t_now = Time.mock_time | ||
80 | + return nil if t_now.nil? | ||
81 | + DateTime.new(t_now.year, t_now.month, t_now.day, t_now.hour, t_now.min, t_now.sec) | ||
82 | + end | ||
83 | + | ||
84 | + # Alias the original now | ||
85 | + alias_method :now_without_mock_time, :now | ||
86 | + | ||
87 | + # Define now_with_mock_time | ||
88 | + def now_with_mock_time | ||
89 | + mock_time || now_without_mock_time | ||
90 | + end | ||
91 | + | ||
92 | + # Alias now to now_with_mock_time | ||
93 | + alias_method :now, :now_with_mock_time | ||
94 | + end | ||
95 | + end | ||
96 | +end | ||
0 | \ No newline at end of file | 97 | \ No newline at end of file |
vendor/gems/jtrupiano-timecop-0.2.1/lib/timecop/timecop.rb
0 → 100644
@@ -0,0 +1,198 @@ | @@ -0,0 +1,198 @@ | ||
1 | +require 'singleton' | ||
2 | +require File.join(File.dirname(__FILE__), 'time_extensions') | ||
3 | +require File.join(File.dirname(__FILE__), 'stack_item') | ||
4 | + | ||
5 | +# Timecop | ||
6 | +# * Wrapper class for manipulating the extensions to the Time, Date, and DateTime objects | ||
7 | +# * Allows us to "freeze" time in our Ruby applications. | ||
8 | +# * Optionally allows time travel to simulate a running clock, such time is not technically frozen. | ||
9 | +# | ||
10 | +# This is very useful when your app's functionality is dependent on time (e.g. | ||
11 | +# anything that might expire). This will allow us to alter the return value of | ||
12 | +# Date.today, Time.now, and DateTime.now, such that our application code _never_ has to change. | ||
13 | +class Timecop | ||
14 | + include Singleton | ||
15 | + | ||
16 | + # Allows you to run a block of code and "fake" a time throughout the execution of that block. | ||
17 | + # This is particularly useful for writing test methods where the passage of time is critical to the business | ||
18 | + # logic being tested. For example: | ||
19 | + # | ||
20 | + # <code> | ||
21 | + # joe = User.find(1) | ||
22 | + # joe.purchase_home() | ||
23 | + # assert !joe.mortgage_due? | ||
24 | + # Timecop.freeze(2008, 10, 5) do | ||
25 | + # assert joe.mortgage_due? | ||
26 | + # end | ||
27 | + # </code> | ||
28 | + # | ||
29 | + # freeze and travel will respond to several different arguments: | ||
30 | + # 1. Timecop.freeze(time_inst) | ||
31 | + # 2. Timecop.freeze(datetime_inst) | ||
32 | + # 3. Timecop.freeze(date_inst) | ||
33 | + # 4. Timecop.freeze(year, month, day, hour=0, minute=0, second=0) | ||
34 | + # | ||
35 | + # When a block is also passed, Time.now, DateTime.now and Date.today are all reset to their | ||
36 | + # previous values. This allows us to nest multiple calls to Timecop.travel and have each block | ||
37 | + # maintain it's concept of "now." | ||
38 | + # | ||
39 | + # * Note: Timecop.freeze will actually freeze time. This can cause unanticipated problems if | ||
40 | + # benchmark or other timing calls are executed, which implicitly expect Time to actually move | ||
41 | + # forward. | ||
42 | + # | ||
43 | + # * Rails Users: Be especially careful when setting this in your development environment in a | ||
44 | + # rails project. Generators will load your environment, including the migration generator, | ||
45 | + # which will lead to files being generated with the timestamp set by the Timecop.freeze call | ||
46 | + # in your dev environment | ||
47 | + def self.freeze(*args, &block) | ||
48 | + instance().send(:travel, :freeze, *args, &block) | ||
49 | + end | ||
50 | + | ||
51 | + # Allows you to run a block of code and "fake" a time throughout the execution of that block. | ||
52 | + # See Timecop#freeze for a sample of how to use (same exact usage syntax) | ||
53 | + # | ||
54 | + # * Note: Timecop.travel will not freeze time (as opposed to Timecop.freeze). This is a particularly | ||
55 | + # good candidate for use in environment files in rails projects. | ||
56 | + def self.travel(*args, &block) | ||
57 | + instance().send(:travel, :move, *args, &block) | ||
58 | + end | ||
59 | + | ||
60 | + # Reverts back to system's Time.now, Date.today and DateTime.now (if it exists). If freeze_all or rebase_all | ||
61 | + # was never called in the first place, this method will have no effect. | ||
62 | + def self.return | ||
63 | + instance().send(:unmock!) | ||
64 | + end | ||
65 | + | ||
66 | + # [Deprecated]: See Timecop#return instead. | ||
67 | + def self.unset_all | ||
68 | + $stderr.puts "Timecop#unset_all is deprecated. Please use Timecop#return instead." | ||
69 | + $stderr.flush | ||
70 | + self.return | ||
71 | + end | ||
72 | + | ||
73 | + protected | ||
74 | + | ||
75 | + def initialize | ||
76 | + @_stack = [] | ||
77 | + end | ||
78 | + | ||
79 | + def travel(mock_type, *args, &block) | ||
80 | + # parse the arguments, build our base time units | ||
81 | + year, month, day, hour, minute, second = parse_travel_args(*args) | ||
82 | + | ||
83 | + # perform our action | ||
84 | + if mock_type == :freeze | ||
85 | + freeze_all(year, month, day, hour, minute, second) | ||
86 | + else | ||
87 | + move_all(year, month, day, hour, minute, second) | ||
88 | + end | ||
89 | + # store this time traveling on our stack... | ||
90 | + @_stack << StackItem.new(mock_type, year, month, day, hour, minute, second) | ||
91 | + | ||
92 | + if block_given? | ||
93 | + begin | ||
94 | + yield | ||
95 | + ensure | ||
96 | + # pull it off the stack... | ||
97 | + stack_item = @_stack.pop | ||
98 | + if @_stack.size == 0 | ||
99 | + # completely unmock if there's nothing to revert back to | ||
100 | + unmock! | ||
101 | + else | ||
102 | + # or reinstantiate the new the top of the stack (could be a :freeze or a :move) | ||
103 | + new_top = @_stack.last | ||
104 | + if new_top.mock_type == :freeze | ||
105 | + freeze_all(new_top.year, new_top.month, new_top.day, new_top.hour, new_top.minute, new_top.second) | ||
106 | + else | ||
107 | + move_all(new_top.year, new_top.month, new_top.day, new_top.hour, new_top.minute, new_top.second) | ||
108 | + end | ||
109 | + end | ||
110 | + end | ||
111 | + end | ||
112 | + end | ||
113 | + | ||
114 | + def unmock! | ||
115 | + Time.unmock! | ||
116 | + end | ||
117 | + | ||
118 | + private | ||
119 | + | ||
120 | + # Re-bases Time.now, Date.today and DateTime.now (if it exists) to use the time passed in. | ||
121 | + # When using this method directly, it is up to the developer to call unset_all to return us | ||
122 | + # to sanity. | ||
123 | + # | ||
124 | + # * If being consumed in a rails app, Time.zone.local will be used to instantiate the time. | ||
125 | + # Otherwise, Time.local will be used. | ||
126 | + def freeze_all(year, month, day, hour=0, minute=0, second=0) | ||
127 | + if Time.respond_to?(:zone) && !Time.zone.nil? | ||
128 | + # ActiveSupport loaded | ||
129 | + time = Time.zone.local(year, month, day, hour, minute, second) | ||
130 | + else | ||
131 | + # ActiveSupport not loaded | ||
132 | + time = Time.local(year, month, day, hour, minute, second) | ||
133 | + end | ||
134 | + | ||
135 | + Time.freeze_time(time) | ||
136 | + end | ||
137 | + | ||
138 | + # Re-bases Time.now, Date.today and DateTime.now to use the time passed in and to continue moving time | ||
139 | + # forward. When using this method directly, it is up to the developer to call return to return us to | ||
140 | + # sanity. | ||
141 | + # | ||
142 | + # * If being consumed in a rails app, Time.zone.local will be used to instantiate the time. | ||
143 | + # Otherwise, Time.local will be used. | ||
144 | + def move_all(year, month, day, hour=0, minute=0, second=0) | ||
145 | + if Time.respond_to?(:zone) && !Time.zone.nil? | ||
146 | + # ActiveSupport loaded | ||
147 | + time = Time.zone.local(year, month, day, hour, minute, second) | ||
148 | + else | ||
149 | + # ActiveSupport not loaded | ||
150 | + time = Time.local(year, month, day, hour, minute, second) | ||
151 | + end | ||
152 | + | ||
153 | + Time.move_time(time) | ||
154 | + end | ||
155 | + | ||
156 | + def parse_travel_args(*args) | ||
157 | + arg = args.shift | ||
158 | + if arg.is_a?(Time) || (Object.const_defined?(:DateTime) && arg.is_a?(DateTime)) | ||
159 | + year, month, day, hour, minute, second = arg.year, arg.month, arg.day, arg.hour, arg.min, arg.sec | ||
160 | + elsif Object.const_defined?(:Date) && arg.is_a?(Date) | ||
161 | + year, month, day, hour, minute, second = arg.year, arg.month, arg.day, 0, 0, 0 | ||
162 | + #puts "#{year}-#{month}-#{day} #{hour}:#{minute}:#{second}" | ||
163 | + elsif args.empty? && arg.kind_of?(Integer) | ||
164 | + t = Time.now + arg | ||
165 | + year, month, day, hour, minute, second = t.year, t.month, t.day, t.hour, t.min, t.sec | ||
166 | + else # we'll just assume it's a list of y/m/h/d/m/s | ||
167 | + year = arg || 0 | ||
168 | + month = args.shift || 1 | ||
169 | + day = args.shift || 1 | ||
170 | + hour = args.shift || 0 | ||
171 | + minute = args.shift || 0 | ||
172 | + second = args.shift || 0 | ||
173 | + end | ||
174 | + return year, month, day, hour, minute, second | ||
175 | + end | ||
176 | +end | ||
177 | + | ||
178 | +#def with_dates(*dates, &block) | ||
179 | +# dates.flatten.each do |date| | ||
180 | +# begin | ||
181 | +# DateTime.forced_now = case date | ||
182 | +# when String: DateTime.parse(date) | ||
183 | +# when Time: DateTime.parse(date.to_s) | ||
184 | +# else | ||
185 | +# date | ||
186 | +# end | ||
187 | +# Date.forced_today = Date.new(DateTime.forced_now.year, | ||
188 | +#DateTime.forced_now.month, DateTime.forced_now.day) | ||
189 | +# yield | ||
190 | +# rescue Exception => e | ||
191 | +# raise e | ||
192 | +# ensure | ||
193 | +# DateTime.forced_now = nil | ||
194 | +# Date.forced_today = nil | ||
195 | +# end | ||
196 | +# end | ||
197 | +#end | ||
198 | + |
vendor/gems/jtrupiano-timecop-0.2.1/lib/timecop/version.rb
0 → 100644
@@ -0,0 +1,20 @@ | @@ -0,0 +1,20 @@ | ||
1 | +module Timecop | ||
2 | + module Version #:nodoc: | ||
3 | + # A method for comparing versions of required modules. It expects two | ||
4 | + # arrays of integers as parameters, the first being the minimum version | ||
5 | + # required, and the second being the actual version available. It returns | ||
6 | + # true if the actual version is at least equal to the required version. | ||
7 | + def self.check(required, actual) #:nodoc: | ||
8 | + required = required.map { |v| "%06d" % v }.join(".") | ||
9 | + actual = actual.map { |v| "%06d" % v }.join(".") | ||
10 | + return actual >= required | ||
11 | + end | ||
12 | + | ||
13 | + MAJOR = 0 | ||
14 | + MINOR = 2 | ||
15 | + TINY = 0 | ||
16 | + | ||
17 | + STRING = [MAJOR, MINOR, TINY].join(".") | ||
18 | + end | ||
19 | +end | ||
20 | + |
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +#!/bin/sh | ||
2 | + | ||
3 | +echo "\033[1;81m Running test_timecop_internals...\033[0m" | ||
4 | +ruby test_timecop_internals.rb || (echo "FAILED!!!!!!!!!!!!") | ||
5 | + | ||
6 | +echo "\033[1;81m Running test_timecop_without_date...\033[0m" | ||
7 | +ruby test_timecop_without_date.rb || (echo "FAILED!!!!!!!!!!!!") | ||
8 | + | ||
9 | +echo "\033[1;81m Running test_timecop...\033[0m" | ||
10 | +ruby test_timecop.rb || (echo "FAILED!!!!!!!!!!!!") |
vendor/gems/jtrupiano-timecop-0.2.1/test/test_timecop.rb
0 → 100644
@@ -0,0 +1,175 @@ | @@ -0,0 +1,175 @@ | ||
1 | + | ||
2 | +require 'date' | ||
3 | +require 'test/unit' | ||
4 | +require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop') | ||
5 | + | ||
6 | +class TestTimecop < Test::Unit::TestCase | ||
7 | + | ||
8 | + def setup | ||
9 | + | ||
10 | + end | ||
11 | + | ||
12 | + # just in case...let's really make sure that Timecop is disabled between tests... | ||
13 | + def teardown | ||
14 | + Timecop.return | ||
15 | + end | ||
16 | + | ||
17 | + def test_freeze_changes_and_resets_time | ||
18 | + # depending on how we're invoked (individually or via the rake test suite) | ||
19 | + assert !Time.respond_to?(:zone) || Time.zone.nil? | ||
20 | + | ||
21 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
22 | + assert_not_equal t, Time.now | ||
23 | + Timecop.freeze(2008, 10, 10, 10, 10, 10) do | ||
24 | + assert_equal t, Time.now | ||
25 | + end | ||
26 | + assert_not_equal t, Time.now | ||
27 | + end | ||
28 | + | ||
29 | + def test_recursive_freeze | ||
30 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
31 | + Timecop.freeze(2008, 10, 10, 10, 10, 10) do | ||
32 | + assert_equal t, Time.now | ||
33 | + t2 = Time.local(2008, 9, 9, 9, 9, 9) | ||
34 | + Timecop.freeze(2008, 9, 9, 9, 9, 9) do | ||
35 | + assert_equal t2, Time.now | ||
36 | + end | ||
37 | + assert_equal t, Time.now | ||
38 | + end | ||
39 | + assert_not_equal t, Time.now | ||
40 | + end | ||
41 | + | ||
42 | + def test_freeze_with_time_instance_works_as_expected | ||
43 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
44 | + Timecop.freeze(t) do | ||
45 | + assert_equal t, Time.now | ||
46 | + assert_equal DateTime.new(2008, 10, 10, 10, 10, 10), DateTime.now | ||
47 | + assert_equal Date.new(2008, 10, 10), Date.today | ||
48 | + end | ||
49 | + assert_not_equal t, Time.now | ||
50 | + assert_not_equal DateTime.new(2008, 10, 10, 10, 10, 10), DateTime.now | ||
51 | + assert_not_equal Date.new(2008, 10, 10), Date.today | ||
52 | + end | ||
53 | + | ||
54 | + def test_freeze_with_datetime_instance_works_as_expected | ||
55 | + t = DateTime.new(2008, 10, 10, 10, 10, 10) | ||
56 | + Timecop.freeze(t) do | ||
57 | + assert_equal t, DateTime.now | ||
58 | + assert_equal Time.local(2008, 10, 10, 10, 10, 10), Time.now | ||
59 | + assert_equal Date.new(2008, 10, 10), Date.today | ||
60 | + end | ||
61 | + assert_not_equal t, DateTime.now | ||
62 | + assert_not_equal Time.local(2008, 10, 10, 10, 10, 10), Time.now | ||
63 | + assert_not_equal Date.new(2008, 10, 10), Date.today | ||
64 | + end | ||
65 | + | ||
66 | + def test_freeze_with_date_instance_works_as_expected | ||
67 | + d = Date.new(2008, 10, 10) | ||
68 | + Timecop.freeze(d) do | ||
69 | + assert_equal d, Date.today | ||
70 | + assert_equal Time.local(2008, 10, 10, 0, 0, 0), Time.now | ||
71 | + assert_equal DateTime.new(2008, 10, 10, 0, 0, 0), DateTime.now | ||
72 | + end | ||
73 | + assert_not_equal d, Date.today | ||
74 | + assert_not_equal Time.local(2008, 10, 10, 0, 0, 0), Time.now | ||
75 | + assert_not_equal DateTime.new(2008, 10, 10, 0, 0, 0), DateTime.now | ||
76 | + end | ||
77 | + | ||
78 | + def test_freeze_with_integer_instance_works_as_expected | ||
79 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
80 | + Timecop.freeze(t) do | ||
81 | + assert_equal t, Time.now | ||
82 | + assert_equal DateTime.new(2008, 10, 10, 10, 10, 10), DateTime.now | ||
83 | + assert_equal Date.new(2008, 10, 10), Date.today | ||
84 | + Timecop.freeze(10) do | ||
85 | + assert_equal t + 10, Time.now | ||
86 | + assert_equal Time.local(2008, 10, 10, 10, 10, 20), Time.now | ||
87 | + assert_equal Date.new(2008, 10, 10), Date.today | ||
88 | + end | ||
89 | + end | ||
90 | + assert_not_equal t, Time.now | ||
91 | + assert_not_equal DateTime.new(2008, 10, 10, 10, 10, 10), DateTime.now | ||
92 | + assert_not_equal Date.new(2008, 10, 10), Date.today | ||
93 | + end | ||
94 | + | ||
95 | + def test_exception_thrown_in_freeze_block_properly_resets_time | ||
96 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
97 | + begin | ||
98 | + Timecop.freeze(t) do | ||
99 | + assert_equal t, Time.now | ||
100 | + raise "blah exception" | ||
101 | + end | ||
102 | + rescue | ||
103 | + assert_not_equal t, Time.now | ||
104 | + assert_nil Time.send(:mock_time) | ||
105 | + end | ||
106 | + end | ||
107 | + | ||
108 | + def test_freeze_freezes_time | ||
109 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
110 | + now = Time.now | ||
111 | + Timecop.freeze(t) do | ||
112 | + #assert Time.now < now, "If we had failed to freeze, time would have proceeded, which is what appears to have happened." | ||
113 | + new_t, new_d, new_dt = Time.now, Date.today, DateTime.now | ||
114 | + assert_equal t, new_t, "Failed to freeze time." # 2 seconds | ||
115 | + #sleep(10) | ||
116 | + assert_equal new_t, Time.now | ||
117 | + assert_equal new_d, Date.today | ||
118 | + assert_equal new_dt, DateTime.now | ||
119 | + end | ||
120 | + end | ||
121 | + | ||
122 | + def test_travel_keeps_time_moving | ||
123 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
124 | + now = Time.now | ||
125 | + Timecop.travel(t) do | ||
126 | + #assert Time.now < now, "If we had failed to freeze, time would have proceeded, which is what appears to have happened." | ||
127 | + assert Time.now - t < 2000, "Looks like we failed to actually travel time" # 2 seconds | ||
128 | + new_t = Time.now | ||
129 | + #sleep(10) | ||
130 | + assert_not_equal new_t, Time.now | ||
131 | + end | ||
132 | + end | ||
133 | + | ||
134 | + def test_recursive_rebasing_maintains_each_context | ||
135 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
136 | + Timecop.travel(2008, 10, 10, 10, 10, 10) do | ||
137 | + assert((t - Time.now).abs < 50, "Failed to travel time.") | ||
138 | + t2 = Time.local(2008, 9, 9, 9, 9, 9) | ||
139 | + Timecop.travel(2008, 9, 9, 9, 9, 9) do | ||
140 | + assert((t2 - Time.now) < 50, "Failed to travel time.") | ||
141 | + assert((t - Time.now) > 1000, "Failed to travel time.") | ||
142 | + end | ||
143 | + assert((t - Time.now).abs < 2000, "Failed to restore previously-traveled time.") | ||
144 | + end | ||
145 | + assert_nil Time.send(:mock_time) | ||
146 | + end | ||
147 | + | ||
148 | + def test_recursive_travel_then_freeze | ||
149 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
150 | + Timecop.travel(2008, 10, 10, 10, 10, 10) do | ||
151 | + assert((t - Time.now).abs < 50, "Failed to travel time.") | ||
152 | + t2 = Time.local(2008, 9, 9, 9, 9, 9) | ||
153 | + Timecop.freeze(2008, 9, 9, 9, 9, 9) do | ||
154 | + assert_equal t2, Time.now | ||
155 | + end | ||
156 | + assert((t - Time.now).abs < 2000, "Failed to restore previously-traveled time.") | ||
157 | + end | ||
158 | + assert_nil Time.send(:mock_time) | ||
159 | + end | ||
160 | + | ||
161 | + def test_recursive_freeze_then_travel | ||
162 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
163 | + Timecop.freeze(t) do | ||
164 | + assert_equal t, Time.now | ||
165 | + t2 = Time.local(2008, 9, 9, 9, 9, 9) | ||
166 | + Timecop.travel(t2) do | ||
167 | + assert((t2 - Time.now) < 50, "Failed to travel time.") | ||
168 | + assert((t - Time.now) > 1000, "Failed to travel time.") | ||
169 | + end | ||
170 | + assert_equal t, Time.now | ||
171 | + end | ||
172 | + assert_nil Time.send(:mock_time) | ||
173 | + end | ||
174 | + | ||
175 | +end | ||
0 | \ No newline at end of file | 176 | \ No newline at end of file |
vendor/gems/jtrupiano-timecop-0.2.1/test/test_timecop_internals.rb
0 → 100644
@@ -0,0 +1,69 @@ | @@ -0,0 +1,69 @@ | ||
1 | + | ||
2 | +require 'date' | ||
3 | +require 'test/unit' | ||
4 | +require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop') | ||
5 | + | ||
6 | +class TestTimecopInternals < Test::Unit::TestCase | ||
7 | + | ||
8 | + def test_parse_travel_args_with_time | ||
9 | + t = Time.now | ||
10 | + y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec | ||
11 | + ty, tm, td, th, tmin, ts = Timecop.instance().send(:parse_travel_args, t) | ||
12 | + assert_equal y, ty | ||
13 | + assert_equal m, tm | ||
14 | + assert_equal d, td | ||
15 | + assert_equal h, th | ||
16 | + assert_equal min, tmin | ||
17 | + assert_equal s, ts | ||
18 | + end | ||
19 | + | ||
20 | + def test_parse_travel_args_with_datetime | ||
21 | + t = DateTime.now | ||
22 | + y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec | ||
23 | + ty, tm, td, th, tmin, ts = Timecop.instance().send(:parse_travel_args, t) | ||
24 | + assert_equal y, ty | ||
25 | + assert_equal m, tm | ||
26 | + assert_equal d, td | ||
27 | + assert_equal h, th | ||
28 | + assert_equal min, tmin | ||
29 | + assert_equal s, ts | ||
30 | + end | ||
31 | + | ||
32 | + def test_parse_travel_args_with_date | ||
33 | + date = Date.today | ||
34 | + y, m, d, h, min, s = date.year, date.month, date.day, 0, 0, 0 | ||
35 | + ty, tm, td, th, tmin, ts = Timecop.instance().send(:parse_travel_args, date) | ||
36 | + assert_equal y, ty | ||
37 | + assert_equal m, tm | ||
38 | + assert_equal d, td | ||
39 | + assert_equal h, th | ||
40 | + assert_equal min, tmin | ||
41 | + assert_equal s, ts | ||
42 | + end | ||
43 | + | ||
44 | + # Due to the nature of this test (calling Time.now once in this test and | ||
45 | + # once in #parse_travel_args), this test may fail when two subsequent calls | ||
46 | + # to Time.now return a different second. | ||
47 | + def test_parse_travel_args_with_integer | ||
48 | + t = Time.now | ||
49 | + y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec | ||
50 | + ty, tm, td, th, tmin, ts = Timecop.instance().send(:parse_travel_args, 0) | ||
51 | + assert_equal y, ty | ||
52 | + assert_equal m, tm | ||
53 | + assert_equal d, td | ||
54 | + assert_equal h, th | ||
55 | + assert_equal min, tmin | ||
56 | + assert_equal s, ts | ||
57 | + end | ||
58 | + | ||
59 | + def test_parse_travel_args_with_individual_arguments | ||
60 | + y, m, d, h, min, s = 2008, 10, 10, 10, 10, 10 | ||
61 | + ty, tm, td, th, tmin, ts = Timecop.instance().send(:parse_travel_args, y, m, d, h, min, s) | ||
62 | + assert_equal y, ty | ||
63 | + assert_equal m, tm | ||
64 | + assert_equal d, td | ||
65 | + assert_equal h, th | ||
66 | + assert_equal min, tmin | ||
67 | + assert_equal s, ts | ||
68 | + end | ||
69 | +end | ||
0 | \ No newline at end of file | 70 | \ No newline at end of file |
vendor/gems/jtrupiano-timecop-0.2.1/test/test_timecop_without_date.rb
0 → 100644
@@ -0,0 +1,120 @@ | @@ -0,0 +1,120 @@ | ||
1 | + | ||
2 | +require 'test/unit' | ||
3 | +require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop') | ||
4 | + | ||
5 | +class TestTimecopWithouDate < Test::Unit::TestCase | ||
6 | + | ||
7 | + def setup | ||
8 | + assert !Object.const_defined?(:Date) | ||
9 | + assert !Object.const_defined?(:DateTime) | ||
10 | + end | ||
11 | + | ||
12 | + # just in case...let's really make sure that Timecop is disabled between tests... | ||
13 | + def teardown | ||
14 | + Timecop.return | ||
15 | + end | ||
16 | + | ||
17 | + def test_freeze_changes_and_resets_time | ||
18 | + # depending on how we're invoked (individually or via the rake test suite) | ||
19 | + assert !Time.respond_to?(:zone) || Time.zone.nil? | ||
20 | + | ||
21 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
22 | + assert_not_equal t, Time.now | ||
23 | + Timecop.freeze(2008, 10, 10, 10, 10, 10) do | ||
24 | + assert_equal t, Time.now | ||
25 | + end | ||
26 | + assert_not_equal t, Time.now | ||
27 | + end | ||
28 | + | ||
29 | + def test_recursive_freeze | ||
30 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
31 | + Timecop.freeze(2008, 10, 10, 10, 10, 10) do | ||
32 | + assert_equal t, Time.now | ||
33 | + t2 = Time.local(2008, 9, 9, 9, 9, 9) | ||
34 | + Timecop.freeze(2008, 9, 9, 9, 9, 9) do | ||
35 | + assert_equal t2, Time.now | ||
36 | + end | ||
37 | + assert_equal t, Time.now | ||
38 | + end | ||
39 | + assert_nil Time.send(:mock_time) | ||
40 | + end | ||
41 | + | ||
42 | + def test_exception_thrown_in_freeze_block_properly_resets_time | ||
43 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
44 | + begin | ||
45 | + Timecop.freeze(t) do | ||
46 | + assert_equal t, Time.now | ||
47 | + raise "blah exception" | ||
48 | + end | ||
49 | + rescue | ||
50 | + assert_not_equal t, Time.now | ||
51 | + assert_nil Time.send(:mock_time) | ||
52 | + end | ||
53 | + end | ||
54 | + | ||
55 | + def test_freeze_freezes_time | ||
56 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
57 | + now = Time.now | ||
58 | + Timecop.freeze(t) do | ||
59 | + #assert Time.now < now, "If we had failed to freeze, time would have proceeded, which is what appears to have happened." | ||
60 | + new_t = Time.now | ||
61 | + assert_equal t, new_t, "Failed to change move time." # 2 seconds | ||
62 | + #sleep(10) | ||
63 | + assert_equal new_t, Time.now | ||
64 | + end | ||
65 | + end | ||
66 | + | ||
67 | + def test_travel_keeps_time_moving | ||
68 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
69 | + now = Time.now | ||
70 | + Timecop.travel(t) do | ||
71 | + #assert Time.now < now, "If we had failed to freeze, time would have proceeded, which is what appears to have happened." | ||
72 | + assert Time.now - t < 2000, "Looks like we failed to actually travel time" # 2 seconds | ||
73 | + new_t = Time.now | ||
74 | + #sleep(10) | ||
75 | + assert_not_equal new_t, Time.now | ||
76 | + end | ||
77 | + end | ||
78 | + | ||
79 | + def test_recursive_rebasing_maintains_each_context | ||
80 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
81 | + Timecop.travel(2008, 10, 10, 10, 10, 10) do | ||
82 | + assert((t - Time.now).abs < 50, "Failed to travel time.") | ||
83 | + t2 = Time.local(2008, 9, 9, 9, 9, 9) | ||
84 | + Timecop.travel(2008, 9, 9, 9, 9, 9) do | ||
85 | + assert((t2 - Time.now) < 50, "Failed to travel time.") | ||
86 | + assert((t - Time.now) > 1000, "Failed to travel time.") | ||
87 | + end | ||
88 | + assert((t - Time.now).abs < 2000, "Failed to restore previously-traveled time.") | ||
89 | + end | ||
90 | + assert_nil Time.send(:mock_time) | ||
91 | + end | ||
92 | + | ||
93 | + def test_recursive_travel_then_freeze | ||
94 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
95 | + Timecop.travel(2008, 10, 10, 10, 10, 10) do | ||
96 | + assert((t - Time.now).abs < 50, "Failed to travel time.") | ||
97 | + t2 = Time.local(2008, 9, 9, 9, 9, 9) | ||
98 | + Timecop.freeze(2008, 9, 9, 9, 9, 9) do | ||
99 | + assert_equal t2, Time.now | ||
100 | + end | ||
101 | + assert((t - Time.now).abs < 2000, "Failed to restore previously-traveled time.") | ||
102 | + end | ||
103 | + assert_nil Time.send(:mock_time) | ||
104 | + end | ||
105 | + | ||
106 | + def test_recursive_freeze_then_travel | ||
107 | + t = Time.local(2008, 10, 10, 10, 10, 10) | ||
108 | + Timecop.freeze(t) do | ||
109 | + assert_equal t, Time.now | ||
110 | + t2 = Time.local(2008, 9, 9, 9, 9, 9) | ||
111 | + Timecop.travel(t2) do | ||
112 | + assert((t2 - Time.now) < 50, "Failed to travel time.") | ||
113 | + assert((t - Time.now) > 1000, "Failed to travel time.") | ||
114 | + end | ||
115 | + assert_equal t, Time.now | ||
116 | + end | ||
117 | + assert_nil Time.send(:mock_time) | ||
118 | + end | ||
119 | + | ||
120 | +end | ||
0 | \ No newline at end of file | 121 | \ No newline at end of file |