ephemeral_response 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.html +72 -0
- data/README.markdown +62 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/lib/ephemeral_response/configuration.rb +34 -0
- data/lib/ephemeral_response/fixture.rb +97 -0
- data/lib/ephemeral_response/net_http.rb +22 -0
- data/lib/ephemeral_response.rb +25 -0
- data/spec/ephemeral_response/configuration_spec.rb +39 -0
- data/spec/ephemeral_response/fixture_spec.rb +95 -0
- data/spec/ephemeral_response/net_http_spec.rb +73 -0
- data/spec/ephemeral_response_spec.rb +32 -0
- data/spec/integration/net_spec.rb +53 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/support/clear_fixtures.rb +6 -0
- data/spec/support/fakefs_ext.rb +14 -0
- data/spec/support/time.rb +19 -0
- metadata +131 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Sandro Turriate
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.html
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
<h1>Ephemeral Response</h1>
|
2
|
+
|
3
|
+
<p><em>Save HTTP responses to give your tests a hint of reality.</em></p>
|
4
|
+
|
5
|
+
<p>This is pretty much NetRecorder without the fakeweb dependency.</p>
|
6
|
+
|
7
|
+
<h2>Premise</h2>
|
8
|
+
|
9
|
+
<ol>
|
10
|
+
<li>run tests</li>
|
11
|
+
<li>all responses are saved to fixtures</li>
|
12
|
+
<li>run tests</li>
|
13
|
+
<li><p>Return the cached response if it exists and isn't out of date.</p>
|
14
|
+
|
15
|
+
<p>If a cached response exists but is out of date, update it with the real response</p>
|
16
|
+
|
17
|
+
<p>Cache the response if it doesn't exist</p></li>
|
18
|
+
</ol>
|
19
|
+
|
20
|
+
|
21
|
+
<h2>Usage</h2>
|
22
|
+
|
23
|
+
<p><code>$ vi spec/spec_helper.rb</code></p>
|
24
|
+
|
25
|
+
<pre><code>require 'ephemeral_response'
|
26
|
+
|
27
|
+
Spec::Runner.configure do |config|
|
28
|
+
config.before(:suite) do
|
29
|
+
EphemeralResponse.activate
|
30
|
+
end
|
31
|
+
config.after(:suite) do
|
32
|
+
EphemeralResponse.deactivate
|
33
|
+
end
|
34
|
+
end
|
35
|
+
</code></pre>
|
36
|
+
|
37
|
+
<h3>Configuration</h3>
|
38
|
+
|
39
|
+
<p>You can change the fixture directory which defaults to "spec/fixtures/ephemeral_response"</p>
|
40
|
+
|
41
|
+
<pre><code>EphemeralResponse::Configuration.fixture_directory = "test/fixtures/ephemeral_response"
|
42
|
+
</code></pre>
|
43
|
+
|
44
|
+
<p>You can change the elapsed time for when a fixture will expire; defaults to 24 hours</p>
|
45
|
+
|
46
|
+
<pre><code>EphemeralResponse::Configuration.expiration = 86400 # 24 hours in seconds
|
47
|
+
</code></pre>
|
48
|
+
|
49
|
+
<p>You can also pass a block when setting expiration which gets instance_eval'd
|
50
|
+
giving you access to the awesome helper method <code>one_day</code></p>
|
51
|
+
|
52
|
+
<pre><code>EphemeralResponse::Configuration.expiration do
|
53
|
+
one_day * 30 # 60 * 60 * 24 * 30
|
54
|
+
end
|
55
|
+
</code></pre>
|
56
|
+
|
57
|
+
<h2>Note on Patches/Pull Requests</h2>
|
58
|
+
|
59
|
+
<ul>
|
60
|
+
<li>Fork the project.</li>
|
61
|
+
<li>Make your feature addition or bug fix.</li>
|
62
|
+
<li>Add tests for it. This is important so I don't break it in a
|
63
|
+
future version unintentionally.</li>
|
64
|
+
<li>Commit, do not mess with rakefile, version, or history.
|
65
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)</li>
|
66
|
+
<li>Send me a pull request. Bonus points for topic branches.</li>
|
67
|
+
</ul>
|
68
|
+
|
69
|
+
|
70
|
+
<h2>Copyright</h2>
|
71
|
+
|
72
|
+
<p>Copyright (c) 2010 Sandro Turriate. See LICENSE for details.</p>
|
data/README.markdown
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
Ephemeral Response
|
2
|
+
==================
|
3
|
+
|
4
|
+
_Save HTTP responses to give your tests a hint of reality._
|
5
|
+
|
6
|
+
This is pretty much NetRecorder without the fakeweb dependency.
|
7
|
+
|
8
|
+
## Premise
|
9
|
+
|
10
|
+
1. run tests
|
11
|
+
2. all responses are saved to fixtures
|
12
|
+
3. run tests
|
13
|
+
4. Return the cached response if it exists and isn't out of date.
|
14
|
+
|
15
|
+
If a cached response exists but is out of date, update it with the real response
|
16
|
+
|
17
|
+
Cache the response if it doesn't exist
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
`$ vi spec/spec_helper.rb`
|
22
|
+
|
23
|
+
require 'ephemeral_response'
|
24
|
+
|
25
|
+
Spec::Runner.configure do |config|
|
26
|
+
config.before(:suite) do
|
27
|
+
EphemeralResponse.activate
|
28
|
+
end
|
29
|
+
config.after(:suite) do
|
30
|
+
EphemeralResponse.deactivate
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
### Configuration
|
35
|
+
You can change the fixture directory which defaults to "spec/fixtures/ephemeral_response"
|
36
|
+
|
37
|
+
EphemeralResponse::Configuration.fixture_directory = "test/fixtures/ephemeral_response"
|
38
|
+
|
39
|
+
You can change the elapsed time for when a fixture will expire; defaults to 24 hours
|
40
|
+
|
41
|
+
EphemeralResponse::Configuration.expiration = 86400 # 24 hours in seconds
|
42
|
+
|
43
|
+
You can also pass a block when setting expiration which gets instance_eval'd
|
44
|
+
giving you access to the awesome helper method `one_day`
|
45
|
+
|
46
|
+
EphemeralResponse::Configuration.expiration do
|
47
|
+
one_day * 30 # 60 * 60 * 24 * 30
|
48
|
+
end
|
49
|
+
|
50
|
+
## Note on Patches/Pull Requests
|
51
|
+
|
52
|
+
* Fork the project.
|
53
|
+
* Make your feature addition or bug fix.
|
54
|
+
* Add tests for it. This is important so I don't break it in a
|
55
|
+
future version unintentionally.
|
56
|
+
* Commit, do not mess with rakefile, version, or history.
|
57
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
58
|
+
* Send me a pull request. Bonus points for topic branches.
|
59
|
+
|
60
|
+
## Copyright
|
61
|
+
|
62
|
+
Copyright (c) 2010 Sandro Turriate. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "ephemeral_response"
|
8
|
+
gem.summary = %Q{Save HTTP responses to give your tests a hint of reality.}
|
9
|
+
gem.description = %Q{
|
10
|
+
Save HTTP responses to give your tests a hint of reality.
|
11
|
+
Responses are saved into your fixtures directory and are used for subsequent web requests until they expire.
|
12
|
+
}
|
13
|
+
gem.email = "sandro.turriate@gmail.com"
|
14
|
+
gem.homepage = "http://github.com/sandro/ephemeral_response"
|
15
|
+
gem.authors = ["Sandro Turriate"]
|
16
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
17
|
+
gem.add_development_dependency "yard", ">= 0"
|
18
|
+
gem.add_development_dependency "fakefs", ">= 0.2.1"
|
19
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
20
|
+
end
|
21
|
+
Jeweler::GemcutterTasks.new
|
22
|
+
rescue LoadError
|
23
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'spec/rake/spectask'
|
27
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
30
|
+
end
|
31
|
+
|
32
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
33
|
+
spec.libs << 'lib' << 'spec'
|
34
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
35
|
+
spec.rcov = true
|
36
|
+
end
|
37
|
+
|
38
|
+
task :spec => :check_dependencies
|
39
|
+
|
40
|
+
task :default => :spec
|
41
|
+
|
42
|
+
begin
|
43
|
+
require 'yard'
|
44
|
+
YARD::Rake::YardocTask.new
|
45
|
+
rescue LoadError
|
46
|
+
task :yardoc do
|
47
|
+
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
48
|
+
end
|
49
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module EphemeralResponse
|
2
|
+
module Configuration
|
3
|
+
extend self
|
4
|
+
|
5
|
+
attr_writer :fixture_directory
|
6
|
+
|
7
|
+
def fixture_directory
|
8
|
+
@fixture_directory || "spec/fixtures/ephemeral_response"
|
9
|
+
end
|
10
|
+
|
11
|
+
def expiration=(expiration)
|
12
|
+
if expiration.is_a?(Proc)
|
13
|
+
expiration = instance_eval &expiration
|
14
|
+
end
|
15
|
+
@expiration = validate_expiration(expiration)
|
16
|
+
end
|
17
|
+
|
18
|
+
def expiration
|
19
|
+
@expiration || one_day
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
def one_day
|
25
|
+
60 * 60 * 24
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate_expiration(expiration)
|
29
|
+
raise TypeError, "expiration must be expressed in seconds" unless expiration.is_a?(Fixnum)
|
30
|
+
expiration
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module EphemeralResponse
|
2
|
+
class Fixture
|
3
|
+
attr_accessor :response
|
4
|
+
attr_reader :method, :uri, :created_at
|
5
|
+
|
6
|
+
def self.fixtures
|
7
|
+
@fixtures ||= {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.clear
|
11
|
+
@fixtures = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.find(uri, method)
|
15
|
+
fixtures[Fixture.new(uri, method).identifier]
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.load_all
|
19
|
+
clear
|
20
|
+
if File.directory?(Configuration.fixture_directory)
|
21
|
+
Dir.glob("#{Configuration.fixture_directory}/*.fixture", &method(:load_fixture))
|
22
|
+
end
|
23
|
+
fixtures
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.load_fixture(file_name)
|
27
|
+
fixture = YAML.load_file file_name
|
28
|
+
if fixture.expired?
|
29
|
+
FileUtils.rm fixture.path
|
30
|
+
else
|
31
|
+
fixtures[fixture.identifier] = fixture
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.respond_to(uri, method)
|
36
|
+
fixture = Fixture.new(uri, method)
|
37
|
+
unless fixtures[fixture.identifier]
|
38
|
+
fixture.response = yield
|
39
|
+
fixture.save
|
40
|
+
fixtures[fixture.identifier] = fixture
|
41
|
+
end
|
42
|
+
fixtures[fixture.identifier].response
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize(uri, method)
|
46
|
+
@method = method
|
47
|
+
@uri = uri
|
48
|
+
@uri.normalize!
|
49
|
+
@created_at = Time.now
|
50
|
+
yield self if block_given?
|
51
|
+
end
|
52
|
+
|
53
|
+
def ==(other)
|
54
|
+
%w(method uri created_at response).all? do |attribute|
|
55
|
+
send(attribute) == other.send(attribute)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def expired?
|
60
|
+
(created_at + Configuration.expiration) < Time.now
|
61
|
+
end
|
62
|
+
|
63
|
+
def file_name
|
64
|
+
@file_name ||= generate_file_name
|
65
|
+
end
|
66
|
+
|
67
|
+
def identifier
|
68
|
+
Digest::SHA1.hexdigest(normalized_name)[0..6]
|
69
|
+
end
|
70
|
+
|
71
|
+
def normalized_name
|
72
|
+
normalized_path = uri.path.gsub(/\/$/, '').gsub('/', '-')
|
73
|
+
[uri.host, method, normalized_path].join("_")
|
74
|
+
end
|
75
|
+
|
76
|
+
def path
|
77
|
+
File.join(Configuration.fixture_directory, file_name)
|
78
|
+
end
|
79
|
+
|
80
|
+
def register
|
81
|
+
FakeWeb.register_uri(method, uri, :response => response)
|
82
|
+
end
|
83
|
+
|
84
|
+
def save
|
85
|
+
FileUtils.mkdir_p Configuration.fixture_directory
|
86
|
+
File.open(path, 'w') do |f|
|
87
|
+
f.write to_yaml
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
protected
|
92
|
+
|
93
|
+
def generate_file_name
|
94
|
+
"#{normalized_name}_#{identifier}.fixture"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Net
|
2
|
+
class HTTP
|
3
|
+
alias request_without_ephemeral_response request
|
4
|
+
alias connect_without_ephemeral_response connect
|
5
|
+
|
6
|
+
def connect
|
7
|
+
end
|
8
|
+
private :connect
|
9
|
+
|
10
|
+
def generate_uri(request)
|
11
|
+
scheme = use_ssl? ? "https" : "http"
|
12
|
+
URI.parse("#{scheme}://#{conn_address}:#{conn_port}#{request.path}")
|
13
|
+
end
|
14
|
+
|
15
|
+
def request(request, body = nil, &block)
|
16
|
+
EphemeralResponse::Fixture.respond_to(generate_uri(request), request.method) do
|
17
|
+
connect_without_ephemeral_response
|
18
|
+
request_without_ephemeral_response(request, body, &block)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'time'
|
4
|
+
require 'digest/sha1'
|
5
|
+
require 'yaml'
|
6
|
+
require 'ephemeral_response/configuration'
|
7
|
+
require 'ephemeral_response/fixture'
|
8
|
+
|
9
|
+
module EphemeralResponse
|
10
|
+
VERSION = "0.1.0".freeze
|
11
|
+
|
12
|
+
def self.activate
|
13
|
+
deactivate
|
14
|
+
load 'ephemeral_response/net_http.rb'
|
15
|
+
Fixture.load_all
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.deactivate
|
19
|
+
Net::HTTP.class_eval do
|
20
|
+
remove_method(:generate_uri) if method_defined?(:generate_uri)
|
21
|
+
alias_method(:connect, :connect_without_ephemeral_response) if private_method_defined?(:connect_without_ephemeral_response)
|
22
|
+
alias_method(:request, :request_without_ephemeral_response) if method_defined?(:request_without_ephemeral_response)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EphemeralResponse::Configuration do
|
4
|
+
subject { EphemeralResponse::Configuration }
|
5
|
+
describe "#fixture_directory" do
|
6
|
+
it "has a default" do
|
7
|
+
subject.fixture_directory.should == "spec/fixtures/ephemeral_response"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "can be overwritten" do
|
11
|
+
subject.fixture_directory = "test/fixtures/ephemeral_response"
|
12
|
+
subject.fixture_directory.should == "test/fixtures/ephemeral_response"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#expiration" do
|
17
|
+
it "defaults to 86400" do
|
18
|
+
subject.expiration.should == 86400
|
19
|
+
end
|
20
|
+
|
21
|
+
it "can be overwritten" do
|
22
|
+
subject.expiration = 43200
|
23
|
+
subject.expiration.should == 43200
|
24
|
+
end
|
25
|
+
|
26
|
+
context "setting a block" do
|
27
|
+
it "returns the value of the block" do
|
28
|
+
subject.expiration = lambda { one_day * 7 }
|
29
|
+
subject.expiration.should == 604800
|
30
|
+
end
|
31
|
+
|
32
|
+
it "raises an error when the return value of the block is not a FixNum" do
|
33
|
+
expect do
|
34
|
+
subject.expiration = lambda { "1 day" }
|
35
|
+
end.to raise_exception(TypeError, "expiration must be expressed in seconds")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EphemeralResponse::Fixture do
|
4
|
+
let(:fixture_directory) { File.expand_path EphemeralResponse::Configuration.fixture_directory }
|
5
|
+
let(:uri) { URI.parse("http://example.com") }
|
6
|
+
let(:fixture) { EphemeralResponse::Fixture.new(uri, 'GET') { |f| f.response = "hello world"} }
|
7
|
+
|
8
|
+
before do
|
9
|
+
clear_fixtures
|
10
|
+
end
|
11
|
+
|
12
|
+
describe ".load_all" do
|
13
|
+
it "returns the empty fixtures hash when the fixture directory doesn't exist" do
|
14
|
+
EphemeralResponse::Fixture.should_not_receive :load_fixture
|
15
|
+
EphemeralResponse::Fixture.load_all.should == {}
|
16
|
+
end
|
17
|
+
|
18
|
+
it "clears old fixtures" do
|
19
|
+
EphemeralResponse::Fixture.should_receive(:clear)
|
20
|
+
EphemeralResponse::Fixture.load_all
|
21
|
+
end
|
22
|
+
|
23
|
+
context "fixture files exist" do
|
24
|
+
before do
|
25
|
+
FileUtils.mkdir_p fixture_directory
|
26
|
+
Dir.chdir(fixture_directory) do
|
27
|
+
FileUtils.touch %w(1.fixture 2.fixture)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "calls #load_fixture for each fixture file" do
|
32
|
+
EphemeralResponse::Fixture.should_receive(:load_fixture).with("#{fixture_directory}/1.fixture")
|
33
|
+
EphemeralResponse::Fixture.should_receive(:load_fixture).with("#{fixture_directory}/2.fixture")
|
34
|
+
EphemeralResponse::Fixture.load_all
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe ".load_fixture" do
|
40
|
+
context "fixture expired" do
|
41
|
+
before do
|
42
|
+
fixture.instance_variable_set(:@created_at, Time.new - (EphemeralResponse::Configuration.expiration * 2))
|
43
|
+
fixture.save
|
44
|
+
end
|
45
|
+
|
46
|
+
it "removes the fixture" do
|
47
|
+
EphemeralResponse::Fixture.load_all
|
48
|
+
File.exists?(fixture.path).should be_false
|
49
|
+
end
|
50
|
+
|
51
|
+
it "does not add the fixture in the fixtures hash" do
|
52
|
+
EphemeralResponse::Fixture.load_all
|
53
|
+
EphemeralResponse::Fixture.fixtures.should_not have_key(fixture.identifier)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "fixture not expired" do
|
58
|
+
before do
|
59
|
+
fixture.save
|
60
|
+
end
|
61
|
+
|
62
|
+
it "adds the the fixture to the fixtures hash" do
|
63
|
+
EphemeralResponse::Fixture.load_all
|
64
|
+
EphemeralResponse::Fixture.fixtures[fixture.identifier].should == fixture
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe ".respond_to" do
|
70
|
+
context "fixture loaded" do
|
71
|
+
it "returns the fixture response" do
|
72
|
+
fixture.save
|
73
|
+
EphemeralResponse::Fixture.load_all
|
74
|
+
response = EphemeralResponse::Fixture.respond_to(fixture.uri, fixture.method)
|
75
|
+
response.should == "hello world"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "fixture not loaded" do
|
80
|
+
it "sets the response to the block" do
|
81
|
+
EphemeralResponse::Fixture.respond_to(fixture.uri, fixture.method) do
|
82
|
+
"new response"
|
83
|
+
end
|
84
|
+
EphemeralResponse::Fixture.fixtures[fixture.identifier].response.should == "new response"
|
85
|
+
end
|
86
|
+
|
87
|
+
it "saves the fixture" do
|
88
|
+
EphemeralResponse::Fixture.respond_to(fixture.uri, fixture.method) do
|
89
|
+
"new response"
|
90
|
+
end
|
91
|
+
File.exists?(fixture.path).should be_true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Net::HTTP do
|
4
|
+
subject { Net::HTTP.new('example.com') }
|
5
|
+
let(:request) { Net::HTTP::Get.new("/foo?q=1") }
|
6
|
+
let(:uri) { URI.parse("http://example.com/foo?q=1") }
|
7
|
+
let(:response) { "Hello" }
|
8
|
+
|
9
|
+
before do
|
10
|
+
subject.stub(:connect_without_ephemeral_response)
|
11
|
+
subject.stub(:request_without_ephemeral_response => response)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#connect" do
|
15
|
+
it "does nothing" do
|
16
|
+
subject.send(:connect).should be_nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#generate_uri" do
|
21
|
+
context "when HTTP" do
|
22
|
+
subject { Net::HTTP.new('example.com') }
|
23
|
+
it "returns the proper http uri object" do
|
24
|
+
subject.generate_uri(request).should == URI.parse("http://example.com/foo?q=1")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when HTTPS" do
|
29
|
+
subject do
|
30
|
+
https = Net::HTTP.new('example.com', 443)
|
31
|
+
https.use_ssl = true
|
32
|
+
https
|
33
|
+
end
|
34
|
+
it "returns the proper http uri object" do
|
35
|
+
subject.generate_uri(request).should == URI.parse("https://example.com/foo?q=1")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#request" do
|
41
|
+
context "fixture does not exist" do
|
42
|
+
before do
|
43
|
+
EphemeralResponse::Fixture.stub(:respond_to).and_yield
|
44
|
+
end
|
45
|
+
|
46
|
+
it "connects" do
|
47
|
+
subject.should_receive(:connect_without_ephemeral_response)
|
48
|
+
subject.request(request)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "calls #request_without_ephemeral_response" do
|
52
|
+
subject.should_receive(:request_without_ephemeral_response).with(request, nil).and_return(response)
|
53
|
+
subject.request(request)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "fixture exists" do
|
58
|
+
before do
|
59
|
+
EphemeralResponse::Fixture.stub(:respond_to => response)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "does not connect" do
|
63
|
+
subject.should_not_receive(:connect_without_ephemeral_response)
|
64
|
+
subject.request(request)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "does not call #request_without_ephemeral_response" do
|
68
|
+
subject.should_not_receive(:request_without_ephemeral_response).with(request, nil).and_return(response)
|
69
|
+
subject.request(request)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe EphemeralResponse do
|
4
|
+
describe ".activate" do
|
5
|
+
it "loads all fixtures" do
|
6
|
+
EphemeralResponse::Fixture.should_receive(:load_all)
|
7
|
+
EphemeralResponse.activate
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe ".deactivate" do
|
12
|
+
before do
|
13
|
+
Net::HTTP.stub(:alias_method)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "restores the original connection method" do
|
17
|
+
Net::HTTP.should_receive(:alias_method).with(:connect, :connect_without_ephemeral_response).once
|
18
|
+
EphemeralResponse.deactivate
|
19
|
+
end
|
20
|
+
|
21
|
+
it "restores the original request method" do
|
22
|
+
Net::HTTP.should_receive(:alias_method).with(:request, :request_without_ephemeral_response)
|
23
|
+
EphemeralResponse.deactivate
|
24
|
+
end
|
25
|
+
|
26
|
+
it "removes #generate_uri" do
|
27
|
+
Net::HTTP.instance_methods.sort.should include('generate_uri')
|
28
|
+
EphemeralResponse.deactivate
|
29
|
+
Net::HTTP.instance_methods.should_not include('generate_uri')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Integrating with the net" do
|
4
|
+
before do
|
5
|
+
clear_fixtures
|
6
|
+
end
|
7
|
+
|
8
|
+
context "example.com" do
|
9
|
+
let(:uri) { URI.parse('http://example.com') }
|
10
|
+
it "generates a fixture, then uses the fixture" do
|
11
|
+
real_response = Net::HTTP.get(uri)
|
12
|
+
fixture = EphemeralResponse::Fixture.new(uri, 'GET')
|
13
|
+
File.exists?(fixture.path).should be_true
|
14
|
+
Net::HTTP.should_not_receive(:connect_without_ephemeral_response)
|
15
|
+
Net::HTTP.should_not_receive(:request_without_ephemeral_response)
|
16
|
+
fixture_response = Net::HTTP.get(uri)
|
17
|
+
real_response.should == fixture_response
|
18
|
+
end
|
19
|
+
|
20
|
+
it "generates a new fixture when the initial fixture expires" do
|
21
|
+
Net::HTTP.get(uri)
|
22
|
+
old_fixture = EphemeralResponse::Fixture.find(uri, 'GET')
|
23
|
+
Time.travel((Time.now + EphemeralResponse::Configuration.expiration * 2).to_s) do
|
24
|
+
EphemeralResponse::Fixture.load_all
|
25
|
+
Net::HTTP.get(uri)
|
26
|
+
end
|
27
|
+
new_fixture = EphemeralResponse::Fixture.find(uri, 'GET')
|
28
|
+
old_fixture.created_at.should < new_fixture.created_at
|
29
|
+
|
30
|
+
# use the new fixture
|
31
|
+
Net::HTTP.should_not_receive(:connect_without_ephemeral_response)
|
32
|
+
Net::HTTP.should_not_receive(:request_without_ephemeral_response)
|
33
|
+
Net::HTTP.get(uri)
|
34
|
+
end
|
35
|
+
|
36
|
+
context "Deactivation" do
|
37
|
+
it "doesn't create any fixtures" do
|
38
|
+
EphemeralResponse.deactivate
|
39
|
+
Net::HTTP.get(uri)
|
40
|
+
File.exists?(EphemeralResponse::Configuration.fixture_directory).should be_false
|
41
|
+
end
|
42
|
+
|
43
|
+
it "reactivates" do
|
44
|
+
EphemeralResponse.deactivate
|
45
|
+
Net::HTTP.get(uri)
|
46
|
+
File.exists?(EphemeralResponse::Configuration.fixture_directory).should be_false
|
47
|
+
EphemeralResponse.activate
|
48
|
+
Net::HTTP.get(uri)
|
49
|
+
File.exists?(EphemeralResponse::Configuration.fixture_directory).should be_true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require 'net/https'
|
3
|
+
require 'ephemeral_response'
|
4
|
+
require 'fakefs/safe'
|
5
|
+
require 'fakefs/spec_helpers'
|
6
|
+
require 'spec/autorun'
|
7
|
+
Dir.glob("spec/support/*.rb") {|f| require f}
|
8
|
+
|
9
|
+
Spec::Runner.configure do |config|
|
10
|
+
config.include FakeFS::SpecHelpers
|
11
|
+
config.include ClearFixtures
|
12
|
+
config.before(:each) do
|
13
|
+
EphemeralResponse.activate
|
14
|
+
end
|
15
|
+
config.after(:suite) do
|
16
|
+
EphemeralResponse.deactivate
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Time
|
2
|
+
class << self
|
3
|
+
alias now_without_travel now
|
4
|
+
|
5
|
+
def travel(travel_string)
|
6
|
+
@travel_string = travel_string
|
7
|
+
yield
|
8
|
+
@travel_string = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def now
|
12
|
+
if @travel_string
|
13
|
+
Time.parse(@travel_string, now_without_travel)
|
14
|
+
else
|
15
|
+
now_without_travel
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ephemeral_response
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Sandro Turriate
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-05-23 00:00:00 -04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 2
|
30
|
+
- 9
|
31
|
+
version: 1.2.9
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: yard
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
44
|
+
type: :development
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: fakefs
|
48
|
+
prerelease: false
|
49
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
segments:
|
54
|
+
- 0
|
55
|
+
- 2
|
56
|
+
- 1
|
57
|
+
version: 0.2.1
|
58
|
+
type: :development
|
59
|
+
version_requirements: *id003
|
60
|
+
description: "\n Save HTTP responses to give your tests a hint of reality.\n Responses are saved into your fixtures directory and are used for subsequent web requests until they expire.\n "
|
61
|
+
email: sandro.turriate@gmail.com
|
62
|
+
executables: []
|
63
|
+
|
64
|
+
extensions: []
|
65
|
+
|
66
|
+
extra_rdoc_files:
|
67
|
+
- LICENSE
|
68
|
+
- README.html
|
69
|
+
- README.markdown
|
70
|
+
files:
|
71
|
+
- .document
|
72
|
+
- .gitignore
|
73
|
+
- LICENSE
|
74
|
+
- README.markdown
|
75
|
+
- Rakefile
|
76
|
+
- VERSION
|
77
|
+
- lib/ephemeral_response.rb
|
78
|
+
- lib/ephemeral_response/configuration.rb
|
79
|
+
- lib/ephemeral_response/fixture.rb
|
80
|
+
- lib/ephemeral_response/net_http.rb
|
81
|
+
- spec/ephemeral_response/configuration_spec.rb
|
82
|
+
- spec/ephemeral_response/fixture_spec.rb
|
83
|
+
- spec/ephemeral_response/net_http_spec.rb
|
84
|
+
- spec/ephemeral_response_spec.rb
|
85
|
+
- spec/integration/net_spec.rb
|
86
|
+
- spec/spec.opts
|
87
|
+
- spec/spec_helper.rb
|
88
|
+
- spec/support/clear_fixtures.rb
|
89
|
+
- spec/support/fakefs_ext.rb
|
90
|
+
- spec/support/time.rb
|
91
|
+
- README.html
|
92
|
+
has_rdoc: true
|
93
|
+
homepage: http://github.com/sandro/ephemeral_response
|
94
|
+
licenses: []
|
95
|
+
|
96
|
+
post_install_message:
|
97
|
+
rdoc_options:
|
98
|
+
- --charset=UTF-8
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
segments:
|
106
|
+
- 0
|
107
|
+
version: "0"
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
segments:
|
113
|
+
- 0
|
114
|
+
version: "0"
|
115
|
+
requirements: []
|
116
|
+
|
117
|
+
rubyforge_project:
|
118
|
+
rubygems_version: 1.3.6
|
119
|
+
signing_key:
|
120
|
+
specification_version: 3
|
121
|
+
summary: Save HTTP responses to give your tests a hint of reality.
|
122
|
+
test_files:
|
123
|
+
- spec/ephemeral_response/configuration_spec.rb
|
124
|
+
- spec/ephemeral_response/fixture_spec.rb
|
125
|
+
- spec/ephemeral_response/net_http_spec.rb
|
126
|
+
- spec/ephemeral_response_spec.rb
|
127
|
+
- spec/integration/net_spec.rb
|
128
|
+
- spec/spec_helper.rb
|
129
|
+
- spec/support/clear_fixtures.rb
|
130
|
+
- spec/support/fakefs_ext.rb
|
131
|
+
- spec/support/time.rb
|