require 'test_helper' class Person include Aversion attr_reader :age, :hunger def initialize(age) @age = age @hunger = 100 end def eat transform do @hunger -= 5 end end end describe Aversion do let(:person) { Person.new(20) } describe 'immutability' do it 'makes objects immutable' do person.frozen?.must_equal true end it 'allows for constructing mutable copies' do Person.new_mutable(20).frozen?.must_equal false end it 'exposes a mutable version of the object' do person.mutable.frozen?.must_equal false person.age.must_equal 20 end end describe '#transform' do it 'returns a new, modified instance' do new_person = person.eat new_person.hunger.must_equal 95 end it 'preserves the original object' do person.eat person.hunger.must_equal 100 end end describe '#rollback' do it 'rolls back to a previous state' do new_person = person.eat new_person.rollback.must_equal person end end describe 'calculating and applying deltas' do let(:new_person) { person.eat } let(:newer_person) { new_person.eat } let(:even_newer_person) { newer_person.eat } let(:difference) { even_newer_person - new_person } describe '#difference' do it 'returns an array of deltas (transformations)' do difference.length.must_equal 2 end end describe '#replay' do it 'returns an array of deltas (transformations)' do new_person.replay(difference).must_equal even_newer_person end end end describe '#==' do describe 'when two objects have the same history' do describe 'and the same initial args' do it 'returns true' do (person.eat.rollback == person).must_equal true end end describe 'but different initial args' do it 'returns false' do (Person.new(10) == person).must_equal false end end end describe 'when two objects differ in history' do it 'returns false' do (person.eat == person).must_equal false end end end end