paper-trail-gem--paper_trail/spec/models/person_spec.rb

180 lines
7.2 KiB
Ruby

# frozen_string_literal: true
require "spec_helper"
# The `Person` model:
#
# - has a dozen associations of various types
# - has a custom serializer, TimeZoneSerializer, for its `time_zone` attribute
RSpec.describe Person, type: :model, versioning: true do
describe "#time_zone" do
it "returns an ActiveSupport::TimeZone" do
person = Person.new(time_zone: "Samoa")
expect(person.time_zone.class).to(eq(ActiveSupport::TimeZone))
end
end
context "when the model is saved" do
it "version.object_changes should store long serialization of TimeZone object" do
person = Person.new(time_zone: "Samoa")
person.save!
len = person.versions.last.object_changes.length
expect((len < 105)).to(be_truthy)
end
it "version.object_changes attribute should have stored the value from serializer" do
person = Person.new(time_zone: "Samoa")
person.save!
as_stored_in_version = HashWithIndifferentAccess[
YAML.load(person.versions.last.object_changes)
]
expect(as_stored_in_version[:time_zone]).to(eq([nil, "Samoa"]))
serialized_value = Person::TimeZoneSerializer.dump(person.time_zone)
expect(as_stored_in_version[:time_zone].last).to(eq(serialized_value))
end
it "version.changeset should convert attribute to original, unserialized value" do
person = Person.new(time_zone: "Samoa")
person.save!
unserialized_value = Person::TimeZoneSerializer.load(person.time_zone)
expect(person.versions.last.changeset[:time_zone].last).to(eq(unserialized_value))
end
it "record.changes (before save) returns the original, unserialized values" do
person = Person.new(time_zone: "Samoa")
changes_before_save = person.changes.dup
person.save!
expect(
changes_before_save[:time_zone].map(&:class)
).to(eq([NilClass, ActiveSupport::TimeZone]))
end
it "version.changeset should be the same as record.changes was before the save" do
person = Person.new(time_zone: "Samoa")
changes_before_save = person.changes.dup
person.save!
actual = person.versions.last.changeset.delete_if { |k, _v| (k.to_sym == :id) }
expect(actual).to(eq(changes_before_save))
actual = person.versions.last.changeset[:time_zone].map(&:class)
expect(actual).to(eq([NilClass, ActiveSupport::TimeZone]))
end
context "when that attribute is updated" do
it "object should not store long serialization of TimeZone object" do
person = Person.new(time_zone: "Samoa")
person.save!
person.assign_attributes(time_zone: "Pacific Time (US & Canada)")
person.save!
len = person.versions.last.object.length
expect((len < 105)).to(be_truthy)
end
it "object_changes should not store long serialization of TimeZone object" do
person = Person.new(time_zone: "Samoa")
person.save!
person.assign_attributes(time_zone: "Pacific Time (US & Canada)")
person.save!
len = person.versions.last.object_changes.length
expect(len < 118).to eq(true)
end
it "version.object attribute should have stored value from serializer" do
person = Person.new(time_zone: "Samoa")
person.save!
attribute_value_before_change = person.time_zone
person.assign_attributes(time_zone: "Pacific Time (US & Canada)")
person.save!
as_stored_in_version = HashWithIndifferentAccess[
YAML.load(person.versions.last.object)
]
expect(as_stored_in_version[:time_zone]).to(eq("Samoa"))
serialized_value = Person::TimeZoneSerializer.dump(attribute_value_before_change)
expect(as_stored_in_version[:time_zone]).to(eq(serialized_value))
end
it "version.object_changes attribute should have stored value from serializer" do
person = Person.new(time_zone: "Samoa")
person.save!
person.assign_attributes(time_zone: "Pacific Time (US & Canada)")
person.save!
as_stored_in_version = HashWithIndifferentAccess[
YAML.load(person.versions.last.object_changes)
]
expect(as_stored_in_version[:time_zone]).to(eq(["Samoa", "Pacific Time (US & Canada)"]))
serialized_value = Person::TimeZoneSerializer.dump(person.time_zone)
expect(as_stored_in_version[:time_zone].last).to(eq(serialized_value))
end
it "version.reify should convert attribute to original, unserialized value" do
person = Person.new(time_zone: "Samoa")
person.save!
attribute_value_before_change = person.time_zone
person.assign_attributes(time_zone: "Pacific Time (US & Canada)")
person.save!
unserialized_value = Person::TimeZoneSerializer.load(attribute_value_before_change)
expect(person.versions.last.reify.time_zone).to(eq(unserialized_value))
end
it "version.changeset should convert attribute to original, unserialized value" do
person = Person.new(time_zone: "Samoa")
person.save!
person.assign_attributes(time_zone: "Pacific Time (US & Canada)")
person.save!
unserialized_value = Person::TimeZoneSerializer.load(person.time_zone)
expect(person.versions.last.changeset[:time_zone].last).to(eq(unserialized_value))
end
it "record.changes (before save) returns the original, unserialized values" do
person = Person.new(time_zone: "Samoa")
person.save!
person.assign_attributes(time_zone: "Pacific Time (US & Canada)")
changes_before_save = person.changes.dup
person.save!
expect(
changes_before_save[:time_zone].map(&:class)
).to(eq([ActiveSupport::TimeZone, ActiveSupport::TimeZone]))
end
it "version.changeset should be the same as record.changes was before the save" do
person = Person.new(time_zone: "Samoa")
person.save!
person.assign_attributes(time_zone: "Pacific Time (US & Canada)")
changes_before_save = person.changes.dup
person.save!
expect(person.versions.last.changeset).to(eq(changes_before_save))
expect(
person.versions.last.changeset[:time_zone].map(&:class)
).to(eq([ActiveSupport::TimeZone, ActiveSupport::TimeZone]))
end
end
end
describe "#cars and bicycles" do
it "can be reified" do
person = Person.create(name: "Frank")
car = Car.create(name: "BMW 325")
bicycle = Bicycle.create(name: "BMX 1.0")
person.car = car
person.bicycle = bicycle
person.update(name: "Steve")
car.update(name: "BMW 330")
bicycle.update(name: "BMX 2.0")
person.update(name: "Peter")
expect(person.reload.versions.length).to(eq(3))
# These will work when PT-AT adds support for the new `item_subtype` column
#
# - https://github.com/westonganger/paper_trail-association_tracking/pull/5
# - https://github.com/paper-trail-gem/paper_trail/pull/1143
# - https://github.com/paper-trail-gem/paper_trail/issues/594
#
# second_version = person.reload.versions.second.reify(has_one: true)
# expect(second_version.car.name).to(eq("BMW 325"))
# expect(second_version.bicycle.name).to(eq("BMX 1.0"))
end
end
end