1
0
Fork 0
mirror of https://github.com/paper-trail-gem/paper_trail.git synced 2022-11-09 11:33:19 -05:00
paper-trail-gem--paper_trail/test/unit/model_test.rb

783 lines
23 KiB
Ruby
Raw Normal View History

2010-03-18 14:02:55 -04:00
require 'test_helper'
2009-05-27 11:21:20 -04:00
2011-02-08 12:16:35 -05:00
class HasPaperTrailModelTest < ActiveSupport::TestCase
2009-10-28 09:12:36 -04:00
context 'A record' do
setup { @article = Article.create }
2010-03-18 14:02:55 -04:00
2009-10-28 09:12:36 -04:00
context 'which updates an ignored column' do
setup { @article.update_attributes :title => 'My first title' }
should_not_change('the number of versions') { Version.count }
end
context 'which updates an ignored column and a selected column' do
2009-10-28 09:12:36 -04:00
setup { @article.update_attributes :title => 'My first title', :content => 'Some text here.' }
should_change('the number of versions', :by => 1) { Version.count }
end
2011-04-01 05:36:56 -04:00
context 'which updates a selected column' do
setup { @article.update_attributes :content => 'Some text here.' }
should_change('the number of versions', :by => 1) { Version.count }
end
context 'which updates a non-ignored and non-selected column' do
setup { @article.update_attributes :abstract => 'Other abstract'}
should_not_change('the number of versions') { Version.count }
end
2011-04-01 05:36:56 -04:00
2009-10-28 09:12:36 -04:00
end
2010-01-06 07:57:54 -05:00
2009-05-27 11:21:20 -04:00
context 'A new record' do
setup { @widget = Widget.new }
should 'not have any previous versions' do
assert_equal [], @widget.versions
end
should 'be live' do
assert @widget.live?
end
2009-05-27 11:21:20 -04:00
context 'which is then created' do
setup { @widget.update_attributes :name => 'Henry' }
should 'have one previous version' do
assert_equal 1, @widget.versions.length
end
should 'be nil in its previous version' do
assert_nil @widget.versions.first.object
assert_nil @widget.versions.first.reify
end
should 'record the correct event' do
assert_match /create/i, @widget.versions.first.event
end
should 'be live' do
assert @widget.live?
end
2009-05-27 11:21:20 -04:00
context 'and then updated without any changes' do
setup { @widget.save }
should 'not have a new version' do
assert_equal 1, @widget.versions.length
end
end
context 'and then updated with changes' do
setup { @widget.update_attributes :name => 'Harry' }
should 'have two previous versions' do
assert_equal 2, @widget.versions.length
end
should 'be available in its previous version' do
assert_equal 'Harry', @widget.name
assert_not_nil @widget.versions.last.object
widget = @widget.versions.last.reify
assert_equal 'Henry', widget.name
assert_equal 'Harry', @widget.name
end
should 'have the same ID in its previous version' do
assert_equal @widget.id, @widget.versions.last.reify.id
end
should 'record the correct event' do
assert_match /update/i, @widget.versions.last.event
end
should 'have versions that are not live' do
assert @widget.versions.map(&:reify).compact.all? { |w| !w.live? }
end
2010-03-18 14:02:55 -04:00
context 'and has one associated object' do
setup do
@wotsit = @widget.create_wotsit :name => 'John'
@reified_widget = @widget.versions.last.reify
end
should 'copy the has_one association when reifying' do
assert_nil @reified_widget.wotsit # wotsit wasn't there at the last version
assert_equal @wotsit, @widget.wotsit # wotsit came into being on the live object
end
end
context 'and has many associated objects' do
setup do
@f0 = @widget.fluxors.create :name => 'f-zero'
@f1 = @widget.fluxors.create :name => 'f-one'
@reified_widget = @widget.versions.last.reify
end
should 'copy the has_many associations when reifying' do
assert_equal @widget.fluxors.length, @reified_widget.fluxors.length
assert_same_elements @widget.fluxors, @reified_widget.fluxors
assert_equal @widget.versions.length, @reified_widget.versions.length
assert_same_elements @widget.versions, @reified_widget.versions
end
end
2009-05-27 11:21:20 -04:00
context 'and then destroyed' do
setup do
@fluxor = @widget.fluxors.create :name => 'flux'
@widget.destroy
2011-02-08 12:16:35 -05:00
@reified_widget = Version.last.reify
end
should 'record the correct event' do
2011-02-08 12:16:35 -05:00
assert_match /destroy/i, Version.last.event
end
2009-05-27 11:21:20 -04:00
should 'have three previous versions' do
2011-02-08 12:16:35 -05:00
assert_equal 3, Version.with_item_keys('Widget', @widget.id).length
2009-05-27 11:21:20 -04:00
end
should 'be available in its previous version' do
assert_equal @widget.id, @reified_widget.id
assert_equal @widget.attributes, @reified_widget.attributes
2009-05-27 11:21:20 -04:00
end
should 'be re-creatable from its previous version' do
assert @reified_widget.save
end
should 'restore its associations on its previous version' do
@reified_widget.save
assert_equal 1, @reified_widget.fluxors.length
2009-05-27 11:21:20 -04:00
end
end
end
end
end
# Test the serialisation and deserialisation.
2009-05-27 11:21:20 -04:00
# TODO: binary
context "A record's papertrail" do
setup do
@date_time = DateTime.now.utc
@time = Time.now
@date = Date.new 2009, 5, 29
@widget = Widget.create :name => 'Warble',
:a_text => 'The quick brown fox',
:an_integer => 42,
:a_float => 153.01,
:a_decimal => 2.71828,
:a_datetime => @date_time,
:a_time => @time,
:a_date => @date,
:a_boolean => true
@widget.update_attributes :name => nil,
:a_text => nil,
:an_integer => nil,
:a_float => nil,
:a_decimal => nil,
:a_datetime => nil,
:a_time => nil,
:a_date => nil,
:a_boolean => false
@previous = @widget.versions.last.reify
end
should 'handle strings' do
assert_equal 'Warble', @previous.name
end
should 'handle text' do
assert_equal 'The quick brown fox', @previous.a_text
end
should 'handle integers' do
assert_equal 42, @previous.an_integer
end
should 'handle floats' do
assert_in_delta 153.01, @previous.a_float, 0.001
end
should 'handle decimals' do
assert_in_delta 2.71828, @previous.a_decimal, 0.00001
end
should 'handle datetimes' do
assert_equal @date_time.to_time.utc, @previous.a_datetime.to_time.utc
2009-05-27 11:21:20 -04:00
end
should 'handle times' do
assert_equal @time, @previous.a_time
end
should 'handle dates' do
assert_equal @date, @previous.a_date
end
should 'handle booleans' do
assert @previous.a_boolean
end
context "after a column is removed from the record's schema" do
setup do
change_schema
Widget.reset_column_information
assert_raise(NoMethodError) { Widget.new.sacrificial_column }
@last = @widget.versions.last
end
should 'reify previous version' do
assert_kind_of Widget, @last.reify
end
should 'restore all forward-compatible attributes' do
2010-03-19 10:37:19 -04:00
assert_equal 'Warble', @last.reify.name
assert_equal 'The quick brown fox', @last.reify.a_text
assert_equal 42, @last.reify.an_integer
assert_in_delta 153.01, @last.reify.a_float, 0.001
assert_in_delta 2.71828, @last.reify.a_decimal, 0.00001
assert_equal @date_time.to_time.utc, @last.reify.a_datetime.to_time.utc
assert_equal @time, @last.reify.a_time
assert_equal @date, @last.reify.a_date
2009-05-27 11:21:20 -04:00
assert @last.reify.a_boolean
end
end
end
context 'A record' do
setup { @widget = Widget.create :name => 'Zaphod' }
context 'with PaperTrail globally disabled' do
setup do
PaperTrail.enabled = false
@count = @widget.versions.length
end
teardown { PaperTrail.enabled = true }
context 'when updated' do
setup { @widget.update_attributes :name => 'Beeblebrox' }
should 'not add to its trail' do
assert_equal @count, @widget.versions.length
end
end
end
2009-05-27 11:21:20 -04:00
context 'with its paper trail turned off' do
setup do
Widget.paper_trail_off
@count = @widget.versions.length
end
teardown { Widget.paper_trail_on }
context 'when updated' do
setup { @widget.update_attributes :name => 'Beeblebrox' }
should 'not add to its trail' do
assert_equal @count, @widget.versions.length
end
end
context 'and then its paper trail turned on' do
setup { Widget.paper_trail_on }
context 'when updated' do
setup { @widget.update_attributes :name => 'Ford' }
should 'add to its trail' do
assert_equal @count + 1, @widget.versions.length
end
end
end
end
end
context 'A papertrail with somebody making changes' do
setup do
@widget = Widget.new :name => 'Fidget'
end
context 'when a record is created' do
setup do
PaperTrail.whodunnit = 'Alice'
@widget.save
@version = @widget.versions.last # only 1 version
end
2009-05-27 11:21:20 -04:00
should 'track who made the change' do
assert_equal 'Alice', @version.whodunnit
assert_nil @version.originator
assert_equal 'Alice', @version.terminator
assert_equal 'Alice', @widget.originator
2009-05-27 11:21:20 -04:00
end
context 'when a record is updated' do
setup do
PaperTrail.whodunnit = 'Bob'
@widget.update_attributes :name => 'Rivet'
@version = @widget.versions.last
end
2009-05-27 11:21:20 -04:00
should 'track who made the change' do
assert_equal 'Bob', @version.whodunnit
assert_equal 'Alice', @version.originator
assert_equal 'Bob', @version.terminator
assert_equal 'Bob', @widget.originator
2009-05-27 11:21:20 -04:00
end
context 'when a record is destroyed' do
setup do
PaperTrail.whodunnit = 'Charlie'
@widget.destroy
2011-02-08 12:16:35 -05:00
@version = Version.last
end
2009-05-27 11:21:20 -04:00
should 'track who made the change' do
assert_equal 'Charlie', @version.whodunnit
assert_equal 'Bob', @version.originator
assert_equal 'Charlie', @version.terminator
assert_equal 'Charlie', @widget.originator
2009-05-27 11:21:20 -04:00
end
end
end
end
end
context 'A subclass' do
setup do
@foo = FooWidget.create
@foo.update_attributes :name => 'Fooey'
end
should 'reify with the correct type' do
thing = @foo.versions.last.reify
assert_kind_of FooWidget, thing
end
context 'when destroyed' do
setup { @foo.destroy }
should 'reify with the correct type' do
thing = @foo.versions.last.reify
assert_kind_of FooWidget, thing
end
end
end
2009-06-19 11:46:33 -04:00
context 'An item with versions' do
setup do
@widget = Widget.create :name => 'Widget'
@widget.update_attributes :name => 'Fidget'
@widget.update_attributes :name => 'Digit'
end
context 'which were created over time' do
setup do
@created = 2.days.ago
@first_update = 1.day.ago
@second_update = 1.hour.ago
@widget.versions[0].update_attributes :created_at => @created
@widget.versions[1].update_attributes :created_at => @first_update
@widget.versions[2].update_attributes :created_at => @second_update
@widget.update_attribute :updated_at, @second_update
end
should 'return nil for version_at before it was created' do
assert_nil @widget.version_at(@created - 1)
end
should 'return how it looked when created for version_at its creation' do
assert_equal 'Widget', @widget.version_at(@created).name
end
should "return how it looked when created for version_at just before its first update" do
assert_equal 'Widget', @widget.version_at(@first_update - 1).name
end
should "return how it looked when first updated for version_at its first update" do
assert_equal 'Fidget', @widget.version_at(@first_update).name
end
should 'return how it looked when first updated for version_at just before its second update' do
assert_equal 'Fidget', @widget.version_at(@second_update - 1).name
end
should 'return how it looked when subsequently updated for version_at its second update' do
assert_equal 'Digit', @widget.version_at(@second_update).name
end
should 'return the current object for version_at after latest update' do
assert_equal 'Digit', @widget.version_at(1.day.from_now).name
end
end
2009-06-19 11:46:33 -04:00
context 'on the first version' do
setup { @version = @widget.versions.first }
should 'have a nil previous version' do
assert_nil @version.previous
end
should 'return the next version' do
assert_equal @widget.versions[1], @version.next
end
2009-06-22 11:37:00 -04:00
should 'return the correct index' do
assert_equal 0, @version.index
end
2009-06-19 11:46:33 -04:00
end
context 'on the last version' do
setup { @version = @widget.versions.last }
should 'return the previous version' do
assert_equal @widget.versions[@widget.versions.length - 2], @version.previous
end
should 'have a nil next version' do
assert_nil @version.next
end
2009-06-22 11:37:00 -04:00
should 'return the correct index' do
assert_equal @widget.versions.length - 1, @version.index
end
2009-06-19 11:46:33 -04:00
end
end
2010-01-06 07:57:54 -05:00
context 'An item' do
setup { @article = Article.new }
context 'which is created' do
setup { @article.save }
should 'store fixed meta data' do
assert_equal 42, @article.versions.last.answer
end
should 'store dynamic meta data which is independent of the item' do
assert_equal '31 + 11 = 42', @article.versions.last.question
end
should 'store dynamic meta data which depends on the item' do
assert_equal @article.id, @article.versions.last.article_id
end
should 'store dynamic meta data based on a method of the item' do
assert_equal @article.action_data_provider_method, @article.versions.last.action
end
2010-01-06 07:57:54 -05:00
context 'and updated' do
setup { @article.update_attributes! :content => 'Better text.' }
should 'store fixed meta data' do
assert_equal 42, @article.versions.last.answer
end
should 'store dynamic meta data which is independent of the item' do
assert_equal '31 + 11 = 42', @article.versions.last.question
end
should 'store dynamic meta data which depends on the item' do
assert_equal @article.id, @article.versions.last.article_id
end
end
2010-06-22 07:29:07 -04:00
context 'and destroyed' do
2010-01-06 07:57:54 -05:00
setup { @article.destroy }
should 'store fixed meta data' do
assert_equal 42, @article.versions.last.answer
end
should 'store dynamic meta data which is independent of the item' do
assert_equal '31 + 11 = 42', @article.versions.last.question
end
should 'store dynamic meta data which depends on the item' do
assert_equal @article.id, @article.versions.last.article_id
end
end
end
end
context 'A reified item' do
setup do
widget = Widget.create :name => 'Bob'
%w( Tom Dick Jane ).each { |name| widget.update_attributes :name => name }
@version = widget.versions.last
@widget = @version.reify
end
should 'know which version it came from' do
assert_equal @version, @widget.version
end
should 'return its previous self' do
assert_equal @widget.versions[-2].reify, @widget.previous_version
end
end
context 'A non-reified item' do
setup { @widget = Widget.new }
should 'not have a previous version' do
assert_nil @widget.previous_version
end
should 'not have a next version' do
assert_nil @widget.next_version
end
context 'with versions' do
setup do
@widget.save
%w( Tom Dick Jane ).each { |name| @widget.update_attributes :name => name }
end
should 'have a previous version' do
assert_equal @widget.versions.last.reify, @widget.previous_version
end
should 'have a next version' do
assert_nil @widget.next_version
end
end
end
context 'A reified item' do
setup do
widget = Widget.create :name => 'Bob'
%w( Tom Dick Jane ).each { |name| widget.update_attributes :name => name }
@versions = widget.versions
@second_widget = @versions[1].reify # first widget is null
@last_widget = @versions.last.reify
end
should 'have a previous version' do
assert_nil @second_widget.previous_version
assert_equal @versions[-2].reify, @last_widget.previous_version
end
should 'have a next version' do
assert_equal @versions[2].reify, @second_widget.next_version
assert_nil @last_widget.next_version
end
end
context ":has_many :through" do
setup do
@book = Book.create :title => 'War and Peace'
@dostoyevsky = Person.create :name => 'Dostoyevsky'
@solzhenitsyn = Person.create :name => 'Solzhenitsyn'
end
should 'store version on source <<' do
count = Version.count
@book.authors << @dostoyevsky
assert_equal 1, Version.count - count
assert_equal Version.last, @book.authorships.first.versions.first
end
should 'store version on source create' do
count = Version.count
@book.authors.create :name => 'Tolstoy'
assert_equal 2, Version.count - count
assert_same_elements [Person.last, Authorship.last], [Version.all[-2].item, Version.last.item]
end
should 'store version on join destroy' do
@book.authors << @dostoyevsky
count = Version.count
@book.authorships(true).last.destroy
assert_equal 1, Version.count - count
assert_equal @book, Version.last.reify.book
assert_equal @dostoyevsky, Version.last.reify.person
end
should 'store version on join clear' do
@book.authors << @dostoyevsky
count = Version.count
@book.authorships(true).clear
assert_equal 1, Version.count - count
assert_equal @book, Version.last.reify.book
assert_equal @dostoyevsky, Version.last.reify.person
end
end
context 'A model with a has_one association' do
setup { @widget = Widget.create :name => 'widget_0' }
2010-10-21 07:33:14 -04:00
context 'before the associated was created' do
setup do
@widget.update_attributes :name => 'widget_1'
@wotsit = @widget.create_wotsit :name => 'wotsit_0'
end
2010-10-21 07:33:14 -04:00
context 'when reified' do
setup { @widget_0 = @widget.versions.last.reify(:has_one => 1) }
2010-10-21 07:33:14 -04:00
should 'see the associated as it was at the time' do
assert_nil @widget_0.wotsit
end
end
end
context 'where the associated is created between model versions' do
setup do
@wotsit = @widget.create_wotsit :name => 'wotsit_0'
make_last_version_earlier @wotsit
@widget.update_attributes :name => 'widget_1'
end
2010-10-21 07:33:14 -04:00
context 'when reified' do
setup { @widget_0 = @widget.versions.last.reify(:has_one => 1) }
2010-10-21 07:33:14 -04:00
should 'see the associated as it was at the time' do
assert_equal 'wotsit_0', @widget_0.wotsit.name
end
end
context 'and then the associated is updated between model versions' do
setup do
@wotsit.update_attributes :name => 'wotsit_1'
make_last_version_earlier @wotsit
@wotsit.update_attributes :name => 'wotsit_2'
make_last_version_earlier @wotsit
@widget.update_attributes :name => 'widget_2'
@wotsit.update_attributes :name => 'wotsit_3'
end
2010-10-21 07:33:14 -04:00
context 'when reified' do
setup { @widget_1 = @widget.versions.last.reify(:has_one => 1) }
2010-10-21 07:33:14 -04:00
should 'see the associated as it was at the time' do
assert_equal 'wotsit_2', @widget_1.wotsit.name
end
end
context 'when reified opting out of has_one reification' do
setup { @widget_1 = @widget.versions.last.reify(:has_one => false) }
should 'see the associated as it is live' do
assert_equal 'wotsit_3', @widget_1.wotsit.name
end
end
end
context 'and then the associated is destroyed between model versions' do
setup do
@wotsit.destroy
make_last_version_earlier @wotsit
@widget.update_attributes :name => 'widget_3'
end
2010-10-21 07:33:14 -04:00
context 'when reified' do
setup { @widget_2 = @widget.versions.last.reify(:has_one => 1) }
2010-10-21 07:33:14 -04:00
should 'see the associated as it was at the time' do
assert_nil @widget_2.wotsit
end
end
end
end
end
context 'A new model instance which uses a custom Version class' do
setup { @post = Post.new }
2011-04-01 05:36:56 -04:00
context 'which is then saved' do
setup { @post.save }
should_change('the number of post versions') { PostVersion.count }
should_not_change('the number of versions') { Version.count }
end
end
2011-04-01 05:36:56 -04:00
context 'An existing model instance which uses a custom Version class' do
setup { @post = Post.create }
2011-04-01 05:36:56 -04:00
context 'on the first version' do
setup { @version = @post.versions.first }
2011-04-01 05:36:56 -04:00
should 'have the correct index' do
assert_equal 0, @version.index
end
end
2011-04-01 05:36:56 -04:00
should 'should have versions of the custom class' do
assert_equal "PostVersion", @post.versions.first.class.name
end
2011-04-01 05:36:56 -04:00
context 'which is modified' do
setup { @post.update_attributes({ :content => "Some new content" }) }
should_change('the number of post versions') { PostVersion.count }
should_not_change('the number of versions') { Version.count }
end
end
2011-04-01 05:36:56 -04:00
context 'An overwritten default accessor' do
setup do
@song = Song.create :length => 4
@song.update_attributes :length => 5
end
should 'return "overwritten" value on live instance' do
assert_equal 5, @song.length
end
should 'return "overwritten" value on reified instance' do
assert_equal 4, @song.versions.last.reify.length
end
end
2010-10-28 13:16:30 -04:00
context 'An unsaved record' do
setup do
@widget = Widget.new
@widget.destroy
end
should 'not have a version created on destroy' do
assert @widget.versions.empty?
end
end
private
# Updates `model`'s last version so it looks like the version was
# created 2 seconds ago.
def make_last_version_earlier(model)
Version.record_timestamps = false
model.versions.last.update_attributes :created_at => 2.seconds.ago
Version.record_timestamps = true
end
2009-05-27 11:21:20 -04:00
end