Permalink
Browse files

Add in more caching specs

  • Loading branch information...
1 parent 3546a46 commit 1ec4b815063de96c053c653bd4aeecf077b4f360 Darcy Laycock committed Feb 6, 2011
Showing with 137 additions and 2 deletions.
  1. +2 −1 .gitignore
  2. +1 −0 Gemfile
  3. +2 −0 Gemfile.lock
  4. +1 −1 lib/rocket_pants/controller/caching.rb
  5. +101 −0 spec/rocket_pants/caching_spec.rb
  6. +30 −0 spec/rocket_pants/controller_spec.rb
View
3 .gitignore
@@ -1,2 +1,3 @@
doc/
-.yardoc/
+.yardoc/
+coverage/
View
1 Gemfile
@@ -2,4 +2,5 @@ source :rubygems
gem 'api_smith', :git => 'git@codebasehq.com:tfg/jammbox/api-smith.git'
gem 'will_paginate', '~> 3.0.pre2'
+gem 'rcov'
gemspec
View
2 Gemfile.lock
@@ -59,6 +59,7 @@ GEM
rake (>= 0.8.7)
thor (~> 0.14.4)
rake (0.8.7)
+ rcov (0.9.9)
rr (1.0.2)
rspec (2.4.0)
rspec-core (~> 2.4.0)
@@ -85,6 +86,7 @@ PLATFORMS
DEPENDENCIES
api_smith!
+ rcov
rocket_pants!
rr (~> 1.0.0)
rspec (~> 2.4.0)
View
2 lib/rocket_pants/controller/caching.rb
@@ -63,7 +63,7 @@ def cache_key_for(object)
if object.respond_to?(:rp_object_key)
Digest::MD5.hexdigest object.rp_object_key
else
- suffix = (object.respond_to?(:new?) && object.new?) ? "new-#{Time.now}" : object.id
+ suffix = (object.respond_to?(:new?) && object.new?) ? "new" : object.id
Digest::MD5.hexdigest "#{object.class.name}/#{suffix}"
end
end
View
101 spec/rocket_pants/caching_spec.rb
@@ -0,0 +1,101 @@
+require 'spec_helper'
+
+describe RocketPants::Caching do
+
+ let(:object) { Object.new.tap { |i| stub(i).id.returns(10) } }
+
+ describe 'dealing with the etag cache' do
+
+ it 'should let you remove an item from the cache' do
+ stub(RocketPants::Caching).cache_key_for(object) { 'my-cache-key' }
+ RocketPants.cache['my-cache-key'] = 'hello there'
+ RocketPants::Caching.remove object
+ RocketPants.cache['my-cache-key'].should be_nil
+ end
+
+ it 'should safely delete a non-existant item from the cache' do
+ expect do
+ RocketPants::Caching.remove object
+ end.to_not raise_error
+ end
+
+ it 'should let you record an object in the cache with a cache_key method' do
+ mock(RocketPants::Caching).cache_key_for(object) { 'my-cache-key' }
+ mock(object).cache_key { 'hello' }
+ RocketPants::Caching.record object
+ RocketPants.cache['my-cache-key'].should == Digest::MD5.hexdigest('hello')
+ end
+
+ it 'should let you record an object in the cache with the default inspect value' do
+ mock(RocketPants::Caching).cache_key_for(object) { 'my-cache-key' }
+ RocketPants::Caching.record object
+ RocketPants.cache['my-cache-key'].should == Digest::MD5.hexdigest(object.inspect)
+ end
+
+ end
+
+ describe 'computing the cache key for an object' do
+
+ it 'should return a md5-like string' do
+ RocketPants::Caching.cache_key_for(object).should =~ /\A[a-z0-9]{32}\Z/
+ end
+
+ it 'should use the rp_object_key method if present' do
+ mock(object).rp_object_key { 'hello' }
+ RocketPants::Caching.cache_key_for(object).should == Digest::MD5.hexdigest('hello')
+ end
+
+ it 'should build a default cache key for records with new? that are new' do
+ mock(object).new? { true }
+ RocketPants::Caching.cache_key_for(object).should == Digest::MD5.hexdigest('Object/new')
+ end
+
+ it 'should build a default cache key for records with new? that are old' do
+ mock(object).new? { false }
+ RocketPants::Caching.cache_key_for(object).should == Digest::MD5.hexdigest('Object/10')
+ end
+
+ it 'should build a default cache key for records without new' do
+ RocketPants::Caching.cache_key_for(object).should == Digest::MD5.hexdigest('Object/10')
+ end
+
+ end
+
+ describe 'normalising an etag' do
+
+ it 'should correctly convert it to the string' do
+ def object.to_s; 'Hello-World'; end
+ mock(object).to_s { 'Hello-World' }
+ described_class.normalise_etag(object).should == '"Hello-World"'
+ end
+
+ it 'should correctly deal with a basic case' do
+ described_class.normalise_etag('SOMETAG').should == '"SOMETAG"'
+ end
+
+ end
+
+ describe 'fetching an object etag' do
+
+ before :each do
+ stub(RocketPants::Caching).cache_key_for(object) { 'my-cache-key' }
+ end
+
+ it 'should use the cache key as a prefix' do
+ RocketPants::Caching.etag_for(object).should =~ /\Amy-cache-key\:/
+ end
+
+ it 'should fetch the recorded etag' do
+ mock(RocketPants.cache)['my-cache-key'].returns 'hello-world'
+ RocketPants::Caching.etag_for(object)
+ end
+
+ it 'should generate a new etag if one does not exist' do
+ mock(RocketPants::Caching).record object, 'my-cache-key'
+ stub(RocketPants.cache)['my-cache-key'].returns nil
+ RocketPants::Caching.etag_for object
+ end
+
+ end
+
+end
View
30 spec/rocket_pants/controller_spec.rb
@@ -83,6 +83,36 @@ def self.controller_class
content[:response].should == {'serialised' => true}
end
+ it 'should correctly hook into paginated responses' do
+ pager = WillPaginate::Collection.create(2, 10) { |p| p.replace %w(a b c d e f g h i j); p.total_entries = 200 }
+ mock(TestController).test_data { pager }
+ hooks = []
+ mock.instance_of(TestController).pre_process_exposed_object(pager, :paginated, false) { hooks << :pre }
+ mock.instance_of(TestController).post_process_exposed_object(pager, :paginated, false) { hooks << :post }
+ get :test_data
+ hooks.should == [:pre, :post]
+ end
+
+ it 'should correctly hook into collection responses' do
+ object = %w(a b c d)
+ mock(TestController).test_data { object }
+ hooks = []
+ mock.instance_of(TestController).pre_process_exposed_object(object, :collection, false) { hooks << :pre }
+ mock.instance_of(TestController).post_process_exposed_object(object, :collection, false) { hooks << :post }
+ get :test_data
+ hooks.should == [:pre, :post]
+ end
+
+ it 'should correctly hook into singular responses' do
+ object = {:a => 1, :b => 2}
+ mock(TestController).test_data { object }
+ hooks = []
+ mock.instance_of(TestController).pre_process_exposed_object(object, :resource, true) { hooks << :pre }
+ mock.instance_of(TestController).post_process_exposed_object(object, :resource, true) { hooks << :post }
+ get :test_data
+ hooks.should == [:pre, :post]
+ end
+
end
describe 'error handling' do

0 comments on commit 1ec4b81

Please sign in to comment.