require 'coveralls' Coveralls.wear! require 'time_for_a_boolean' describe TimeForABoolean do it 'defines the attribute method' do klass.time_for_a_boolean :attribute expect(klass.new).to respond_to :attribute end it 'defines the query method' do klass.time_for_a_boolean :attribute expect(klass.new).to respond_to :attribute? end it 'defines the attribute writer' do klass.time_for_a_boolean :attribute expect(klass.new).to respond_to :attribute= end it 'defines the bangable method to act as an implicit writer' do klass.time_for_a_boolean :attribute expect(klass.new).to respond_to :attribute! end describe 'attribute method' do it 'calls nil? on the backing timestamp' do klass.time_for_a_boolean :attribute timestamp = double(nil?: true) allow(object).to receive(:attribute_at).and_return(timestamp) object.attribute expect(timestamp).to have_received(:nil?) end it 'is true if the attribute is not nil' do klass.time_for_a_boolean :attribute allow(object).to receive(:attribute_at).and_return(Time.now - 10) expect(object.attribute).to be_truthy end it 'is false if the attribute is nil' do klass.time_for_a_boolean :attribute allow(object).to receive(:attribute_at) expect(object.attribute).to be_falsey end it 'is false if the attribute time is in the future' do klass.time_for_a_boolean :attribute allow(object).to receive(:attribute_at).and_return(Time.now + 86400) # one day in the future expect(object.attribute).to be_falsey end context 'when the user has defined their own attribute name' do it 'calls nil? on the backing value' do klass.time_for_a_boolean :attribute, :attribute_on date = double(nil?: true) allow(object).to receive(:attribute_on).and_return(date) object.attribute expect(date).to have_received(:nil?) end it 'is true if the attribute is not nil' do klass.time_for_a_boolean :attribute, :attribute_on allow(object).to receive(:attribute_on).and_return(Date.current - 10) expect(object.attribute).to be_truthy end it 'is false if the attribute is nil' do klass.time_for_a_boolean :attribute, :attribute_on allow(object).to receive(:attribute_on) expect(object.attribute).to be_falsey end it 'is false if the attribute date is in the future' do klass.time_for_a_boolean :attribute, :attribute_on allow(object).to receive(:attribute_on).and_return(Date.current + 1) expect(object.attribute).to be_falsey end end end describe 'the query method' do it 'is an alias for the attribute method' do klass.time_for_a_boolean :attribute expect(object.method(:attribute?)).to eq object.method(:attribute) end end describe 'the writer method' do it 'sets the timestamp to now if value is true' do klass.time_for_a_boolean :attribute klass.send(:attr_accessor, :attribute_at) object.attribute = true expect(object.attribute_at).to be_kind_of(Time) end it 'sets the timestamp to nil if value is false' do klass.time_for_a_boolean :attribute klass.send(:attr_accessor, :attribute_at) object.attribute_at = Time.now object.attribute = false expect(object.attribute_at).to be_nil end it 'works with other representations of true' do klass.time_for_a_boolean :attribute klass.send(:attr_accessor, :attribute_at) object.attribute = '1' expect(object.attribute_at).to be_kind_of(Time) end it 'works with other representations of false' do klass.time_for_a_boolean :attribute klass.send(:attr_accessor, :attribute_at) object.attribute_at = Time.now object.attribute = '0' expect(object.attribute_at).to be_nil end end describe 'the bangable method' do it 'sets the timestamp to now' do klass.time_for_a_boolean :attribute klass.send(:attr_accessor, :attribute_at) object.attribute! expect(object.attribute_at).to be_kind_of(Time) end end def klass @klass ||= Class.new do extend TimeForABoolean end end def object @object ||= klass.new end end