spec/resource_spec.rb in kissifer-hash-persistent-0.2.2 vs spec/resource_spec.rb in kissifer-hash-persistent-0.3.1
- old
+ new
@@ -23,11 +23,24 @@
self.dummy == other.dummy
end
end
describe "A class that includes HashPersistent::Resource" do
- context "(class methods)" do
+ context "(not initially useful)" do
+ it "not gain much from the module" do
+ # Grey-box here...
+ lambda{ResourceFoo.store}.should raise_error
+ lambda{ResourceFoo.prefix}.should raise_error
+ lambda{ResourceFoo.on_save}.should raise_error
+ lambda{ResourceFoo.on_delete}.should raise_error
+ lambda{ResourceFoo.find}.should raise_error
+
+ ResourceFoo.new.respond_to?(:key=).should be_false
+ ResourceFoo.new.respond_to?(:save).should be_false
+ ResourceFoo.new.respond_to?(:delete).should be_false
+ end
+
it "should acquire a persist_to class method" do
ResourceFoo.respond_to?(:persist_to).should be_true
end
end
@@ -41,285 +54,302 @@
end
it "should reject a non-string-like prefix" do
lambda {ResourceFoo.persist_to({}, Dummy_NoStringRep.new)}.should raise_error(ArgumentError)
end
- end
-
+
+ it "should return a sub-class in response to persist_to" do
+ resource_class = ResourceFoo.persist_to({}, "")
+ resource_class.should_not == ResourceFoo
+ resource_class.superclass.should == ResourceFoo
+ end
+
+ it "should return a different sub-class each time" do
+ resource_class_1 = ResourceFoo.persist_to({}, "")
+ resource_class_2 = ResourceFoo.persist_to({}, "")
+ resource_class_1.should_not == resource_class_2
+ end
+
+ it "should return a sub-class that references the correct store and prefix" do
+ store = Hash.new
+ store["foo"] = "bar"
+ prefix = "baz"
+ resource_class = ResourceFoo.persist_to(store, prefix)
+ resource_class.store.should == store
+ resource_class.prefix.should == prefix
+ end
+
+ it "should return not cross-contaminate the store and prefix of subclasses" do
+ store_1 = Hash.new
+ store_1["foo"] = "bar"
+ prefix_1 = "baz"
+ resource_class_1 = ResourceFoo.persist_to(store_1, prefix_1)
+ resource_class_2 = ResourceFoo.persist_to(store_1, prefix_1)
+
+ store_3 = Hash.new
+ store_3["fred"] = "barney"
+ prefix_3 = "wilma"
+ resource_class_3 = ResourceFoo.persist_to(store_3, prefix_3)
+
+ resource_class_1.store.should == resource_class_2.store
+ resource_class_1.prefix.should == resource_class_2.prefix
+
+ resource_class_1.store.should_not == resource_class_3.store
+ resource_class_1.prefix.should_not == resource_class_3.prefix
+
+ resource_class_1.store.should == store_1
+ resource_class_2.store.should == store_1
+ resource_class_3.store.should == store_3
+
+ resource_class_1.prefix.should == prefix_1
+ resource_class_2.prefix.should == prefix_1
+ resource_class_3.prefix.should == prefix_3
+ end
+ end
+
context "(an instance that has not been saved)" do
+ before(:each) do
+ @resource_class = ResourceFoo.persist_to({}, "")
+ end
+
it "should maintain a key attribute" do
- ResourceFoo.new.respond_to?(:key).should be_true
- ResourceFoo.new.respond_to?(:key=).should be_true
+ @resource_class.new.respond_to?(:key).should be_true
+ @resource_class.new.respond_to?(:key=).should be_true
end
it "should respond to a save method" do
- ResourceFoo.new.respond_to?(:save).should be_true
+ @resource_class.new.respond_to?(:save).should be_true
end
it "should respond to a delete method" do
- ResourceFoo.new.respond_to?(:delete).should be_true
+ @resource_class.new.respond_to?(:delete).should be_true
end
it "should not save unless the key has been explictly set" do
- lambda{ResourceFoo.new.save}.should raise_error
+ lambda{@resource_class.new.save}.should raise_error
end
it "should not delete unless the key has been explictly set" do
- lambda{ResourceFoo.new.delete}.should raise_error
+ lambda{@resource_class.new.delete}.should raise_error
end
it "should not complain when deleted, even after a key is set" do
- ResourceFoo.persist_to(Hash.new, "")
- resource = ResourceFoo.new
+ resource = @resource_class.new
resource.key = "fred"
lambda{resource.delete}.should_not raise_error
end
it "should not be findable via its key" do
- ResourceFoo.persist_to(Hash.new, "")
- resource = ResourceFoo.new
+ resource = @resource_class.new
resource.key = "fred"
- ResourceFoo.find("fred").should == nil
- ResourceFoo.find("barney").should == nil
+ @resource_class.find("fred").should == nil
+ @resource_class.find("barney").should == nil
end
end
context "(an instance that has been saved)" do
+ before(:each) do
+ @resource_class = ResourceFoo.persist_to({}, "")
+ @resource_class_with_state = ResourceFooWithState.persist_to({}, "")
+ end
+
it "should be findable via its key" do
- ResourceFoo.persist_to(Hash.new, "")
- resource = ResourceFoo.new
+ resource = @resource_class.new
resource.key = "fred"
resource.save
- ResourceFoo.find("fred").should_not be_nil
+ @resource_class.find("fred").should_not be_nil
end
it "should correctly recover all of its state" do
- ResourceFooWithState.persist_to(Hash.new, "")
- resource = ResourceFooWithState.new
+ resource = @resource_class_with_state.new
resource.key = "fred"
resource.dummy = ["something random", {}]
resource.save
resource_dup = resource.dup
- ResourceFooWithState.find("fred").should == resource_dup
+ @resource_class_with_state.find("fred").should == resource_dup
end
it "should be deletable" do
- ResourceFoo.persist_to(Hash.new, "")
- resource = ResourceFoo.new
+ resource = @resource_class.new
resource.key = "fred"
resource.save
lambda{resource.delete}.should_not raise_error
end
it "should save a new state when asked" do
- ResourceFooWithState.persist_to(Hash.new, "")
- resource = ResourceFooWithState.new
+ resource = @resource_class_with_state.new
resource.key = "fred"
resource.dummy = ["something random", {}]
resource.save
resource_dup_1 = resource.dup
resource.dummy = ["something else random", 1]
resource.save
resource_dup_2 = resource.dup
- ResourceFooWithState.find("fred").should_not == resource_dup_1
- ResourceFooWithState.find("fred").should == resource_dup_2
+ @resource_class_with_state.find("fred").should_not == resource_dup_1
+ @resource_class_with_state.find("fred").should == resource_dup_2
end
end
context "(an instance that has been saved and then deleted)" do
+ before(:each) do
+ @resource_class = ResourceFoo.persist_to({}, "")
+ end
+
it "should not be findable via its key" do
- ResourceFoo.persist_to(Hash.new, "")
- resource = ResourceFoo.new
+ resource = @resource_class.new
resource.key = "fred"
resource.save
resource.delete
- ResourceFoo.find("fred").should == nil
+ @resource_class.find("fred").should == nil
end
it "should not complain when deleted" do
- ResourceFoo.persist_to(Hash.new, "")
- resource = ResourceFoo.new
+ resource = @resource_class.new
resource.key = "fred"
resource.save
resource.delete
lambda{resource.delete}.should_not raise_error
end
end
context "(use of prefix to namespace keys)" do
+ before(:each) do
+ @resource_class = ResourceFoo.persist_to({}, "a_random_namespace::")
+ end
+
it "should (transparently) prepend the supplied prefix to the key of the saved instance" do
- store = Hash.new
- ResourceFoo.persist_to(store, "a_random_namespace::")
- resource = ResourceFoo.new
+ resource = @resource_class.new
resource.key = "fred"
resource.save
- store.should_not have_key("fred")
- store.should have_key("a_random_namespace::fred")
+ @resource_class.store.should_not have_key("fred")
+ @resource_class.store.should have_key("a_random_namespace::fred")
end
it "should find instances when using a namespace, using only the key" do
- store = Hash.new
- ResourceFoo.persist_to(store, "a_random_namespace::")
- resource = ResourceFoo.new
+ resource = @resource_class.new
resource.key = "fred"
resource.save
- ResourceFoo.find("fred").should_not == nil
+ @resource_class.find("fred").should_not == nil
end
it "should not find instances when mistakenly given a namespaced key" do
- store = Hash.new
- ResourceFoo.persist_to(store, "a_random_namespace::")
- resource = ResourceFoo.new
+ resource = @resource_class.new
resource.key = "fred"
resource.save
- ResourceFoo.find("a_random_namespace::fred").should == nil
+ @resource_class.find("a_random_namespace::fred").should == nil
end
it "should correctly delete an instance from the store when using a prefix" do
- store = Hash.new
- ResourceFoo.persist_to(store, "a_random_namespace::")
- resource = ResourceFoo.new
+ resource = @resource_class.new
resource.key = "fred"
resource.save
resource.delete
- ResourceFoo.find("fred").should == nil
+ @resource_class.find("fred").should == nil
+ @resource_class.store.should == {}
end
end
context "(use of store)" do
it "should correctly delete items from the store" do
- store = Hash.new
- ResourceFoo.persist_to(store, "")
- resource_1 = ResourceFoo.new
+ @resource_class = ResourceFoo.persist_to({}, "")
+ resource_1 = @resource_class.new
resource_1.key = "fred"
resource_1.save
- resource_2 = ResourceFoo.new
+ resource_2 = @resource_class.new
resource_2.key = "barney"
resource_2.save
- store.should_not == Hash.new
+ @resource_class.store.should_not == {}
resource_1.delete
+ @resource_class.store.should_not == {}
+
resource_2.delete
- store.should == Hash.new
+ @resource_class.store.should == {}
end
end
-
+
context "(use of restricted hash api)" do
it "should use only the restricted hash api provided by moneta" do
lambda {
- ResourceFooWithState.persist_to(Dummy_RestrictedHash.new, "prefix::")
- resource_1 = ResourceFooWithState.new
+ @resource_class = ResourceFooWithState.persist_to(Dummy_RestrictedHash.new, "prefix::")
+ resource_1 = @resource_class.new
resource_1.key = "fred"
resource_1.dummy = ["barney"]
resource_1.save
- ResourceFooWithState.find("fred").delete
+ @resource_class.find("fred").delete
}.should_not raise_error
end
end
-
- context "(default store)" do
- it "should function with a vdefault store/prefix if none is supplied" do
- # This is implicitly tested elsewhere. Which makes this test documentation, I guess
- resource_1 = ResourceFooOnlyUsedOnce.new
- resource_1.key = "fred"
- resource_1.dummy = ["barney"]
- resource_1.save
- ResourceFooOnlyUsedOnce.find("fred").should == resource_1.dup
- lambda {ResourceFooOnlyUsedOnce.find("fred").delete}.should_not raise_error
- end
- end
-
- context "(multiple classes using module)" do
- # TODO: should check the callbacks here? Seems over the top...
- it "should not cross-contaminate classes that include the module" do
- store_1 = Hash.new
- ResourceFoo.persist_to(store_1, "")
- store_2 = Hash.new
- ResourceFooWithState.persist_to(store_2, "prefix::")
-
- store_1.should == Hash.new
- store_2.should == Hash.new
-
- resource_1 = ResourceFoo.new
- resource_1.key = "1"
- resource_1.save
-
- store_1.should_not == Hash.new
- store_2.should == Hash.new
- store_1.should have_key("1")
- store_1.should_not have_key("prefix::1")
-
- resource_1.delete
-
- store_1.should == Hash.new
- store_2.should == Hash.new
-
- resource_2 = ResourceFooWithState.new
- resource_2.key = "2"
- resource_2.save
-
- store_1.should == Hash.new
- store_2.should_not == Hash.new
- store_2.should have_key("prefix::2")
- store_2.should_not have_key("2")
-
- resource_2.delete
-
- store_1.should == Hash.new
- store_2.should == Hash.new
- end
- end
context "(callbacks)" do
it "should allow a class level callback to be set and retrieved for save events" do
- ResourceFoo.on_save.should == nil
- lambda{ResourceFoo.on_save do
+ @resource_class = ResourceFoo.persist_to({}, "")
+ @resource_class.on_save.should == nil
+
+ @resource_class.on_save do
"thing"
- end}.should_not raise_error
- ResourceFoo.on_save.call.should == "thing"
- lambda{ResourceFoo.on_save(1)}.should raise_error
+ end
+ @resource_class.on_save.call.should == "thing"
end
it "should allow a class level callback to be set and retrieved for delete events" do
- ResourceFoo.on_delete.should == nil
- lambda{ResourceFoo.on_delete do
+ @resource_class = ResourceFoo.persist_to({}, "")
+ @resource_class.on_delete.should == nil
+ @resource_class.on_delete do
"thing"
- end}.should_not raise_error
- ResourceFoo.on_delete.call.should == "thing"
- lambda{ResourceFoo.on_delete(1)}.should raise_error
+ end
+ @resource_class.on_delete.call.should == "thing"
end
it "should yield an instance to the save callback when the instance is saved" do
+ @resource_class = ResourceFoo.persist_to({}, "")
yielded_instance = nil
- ResourceFoo.on_save do |yielded|
+ @resource_class.on_save do |yielded|
yielded_instance = yielded
end
- instance = ResourceFoo.new
- instance.key = "1"
+ instance = @resource_class.new
+ instance.key = "fah"
instance.save
yielded_instance.should_not == nil
yielded_instance.should == instance
end
it "should yield an instance to the delete callback when the instance is deleted" do
+ @resource_class = ResourceFoo.persist_to({}, "")
yielded_instance = nil
- ResourceFoo.on_delete do |yielded|
+ @resource_class.on_delete do |yielded|
yielded_instance = yielded
end
- instance = ResourceFoo.new
- instance.key = "1"
+ instance = @resource_class.new
+ instance.key = "bah"
instance.save
instance.delete
yielded_instance.should_not == nil
yielded_instance.should == instance
end
+ it "should maintain separate callbacks for each created subclass" do
+ @resource_class_1 = ResourceFoo.persist_to({}, "")
+ @resource_class_2 = ResourceFoo.persist_to({}, "")
+
+ @resource_class_1.on_save do "on_save_1" end
+ @resource_class_1.on_delete do "on_delete_1" end
+
+ @resource_class_2.on_save do "on_save_2" end
+ @resource_class_2.on_delete do "on_delete_2" end
+
+ @resource_class_1.on_delete.call.should == "on_delete_1"
+ @resource_class_1.on_save.call.should == "on_save_1"
+
+ @resource_class_2.on_delete.call.should == "on_delete_2"
+ @resource_class_2.on_save.call.should == "on_save_2"
+ end
end
end