require File.expand_path(File.dirname(__FILE__) + '/spec_helper') ActiveRecord::Schema.define(:version => 0) do create_table :test_models, :force => true do |t| t.column "name", :string t.column "count", :integer end end class TestModel < ActiveRecord::Base acts_as_undoable end describe "Basic Undo Redo" do def change(description, undo_link, redo_link, &block) UndoManager.current.change(description, undo_link, redo_link, &block) end before(:each) do TestModel.destroy_all UndoManager.current = nil end it "should record create model" do change("create model", "undo", "redo") do test_model = TestModel.create(:name => 'joe', :count =>4) end undo_manager = UndoManager.current undo_manager.undo_actions.count(:all).should == 1 undoAction = undo_manager.undo_actions.find(:first) undoAction.undo_records.count.should == 1 end it "should record update model" do test_model = TestModel.create(:name => 'joe', :count =>4) test_model.save! change("create model", "undo", "redo") do test_model.name = "jane" test_model.save end undo_manager = UndoManager.current undo_manager.undo_actions.count(:all).should == 1 undoAction = undo_manager.undo_actions[0] undoAction.undo_records.count.should == 1 end it "should record delete model" do test_model = TestModel.create(:name => 'joe', :count =>4) change("create model", "undo", "redo") do test_model.destroy end undo_manager = UndoManager.current undo_manager.undo_actions.count(:all).should == 1 undoAction = undo_manager.undo_actions[0] undoAction.undo_records.count.should == 1 end it "should record all operations on model" do change("lots of modfications", "undo", "redo") do test_model1 = TestModel.create(:name => 'joe', :count =>4) test_model1.name = "jane" test_model1.save test_model2 = TestModel.create(:name => 'jake', :count =>4) end change("more modifications and destroy", "undo", "redo") do test_model = TestModel.find(1) test_model.name = "aimee" test_model.save test_model.destroy end undo_manager = UndoManager.current undo_manager.undo_actions.count(:all).should == 2 undoAction0 = undo_manager.undo_actions[0] undoAction0.undo_records.count.should == 3 undoAction1 = undo_manager.undo_actions[1] undoAction1.undo_records.count.should == 2 end it "should undo create model, then redo" do change("create model", "undo", "redo") do test_model = TestModel.create(:name => 'joe', :count =>4) end UndoManager.current.undo_description.should == "create model" UndoManager.current.redo_description.should == nil UndoManager.current.undo TestModel.count(:all).should == 0 UndoManager.current.undo_description.should == nil UndoManager.current.redo_description.should == "create model" UndoManager.current.redo TestModel.count(:all).should == 1 end it "should undo update model, then redo" do change("create model", "undo", "redo") do test_model = TestModel.create(:name => 'joe', :count =>4) end change("update model", "undo", "redo") do test_model = TestModel.find 1 test_model.name = "aimee" test_model.save end UndoManager.current.undo_description.should == "update model" UndoManager.current.redo_description.should == nil UndoManager.current.undo test_model = TestModel.find 1 test_model.name.should == "joe" UndoManager.current.undo_description.should == "create model" UndoManager.current.redo_description.should == "update model" UndoManager.current.redo test_model.reload test_model.name.should == "aimee" end it "should undo destroy model, then redo" do test_model = TestModel.create(:name => 'joe', :count =>4) change("delete model", "undo", "redo") do test_model.destroy end UndoManager.current.undo TestModel.count(:all).should == 1 UndoManager.current.redo TestModel.count(:all).should == 0 end it "should clear redo when new change is recorded" do change("create model", "undo", "redo") do test_model = TestModel.create(:name => 'joe', :count =>4) end change("update model", "undo", "redo") do test_model = TestModel.find 1 test_model.name = "aimee" test_model.save end undo_manager = UndoManager.current undo_manager.undo undo_manager.undo_actions.count(:all).should == 2 change("update model #2", "undo", "redo") do test_model = TestModel.find 1 test_model.name = "jack" test_model.save end undo_manager.undo_actions.count(:all).should == 2 end it "should keep the undo stack no deeper than undo_depth" do UNDO_DEPTH = 3 UndoManager.undo_depth = UNDO_DEPTH undo_manager = UndoManager.current undo_manager.undo_actions.count(:all).should <= UNDO_DEPTH change("create model1", "undo1", "redo1") do test_model = TestModel.create(:name => 'joe', :count =>1) end undo_manager.undo_actions.count(:all).should <= UNDO_DEPTH change("create model2", "undo2", "redo2") do test_model = TestModel.create(:name => 'aimee', :count =>2) end undo_manager.undo_actions.count(:all).should <= UNDO_DEPTH change("create model3", "undo3", "redo3") do test_model = TestModel.create(:name => 'jake', :count =>3) end undo_manager.undo_actions.count(:all).should <= UNDO_DEPTH change("create model4", "undo4", "redo4") do test_model = TestModel.create(:name => 'lisa', :count =>4) end undo_manager.undo_actions.count(:all).should <= UNDO_DEPTH undo_manager.undo_actions.find(:first, {:conditions => ['description = ?', "create model1"]}).should == nil end it "should not undo when nothing to undo" do undo_manager = UndoManager.current undo_manager.undo end it "should not redo when nothing to redo" do undo_manager = UndoManager.current undo_manager.redo end end