require 'minitest/autorun' require 'geometry/point_iso' describe Geometry::PointIso do let(:iso_value) { 5 } subject { Geometry::PointIso.new(5) } it 'must pop' do subject.pop.must_equal Point[5] subject.pop(2).must_equal Point[5, 5] end it 'must shift' do subject.shift.must_equal Point[5] subject.shift(2).must_equal Point[5, 5] end describe 'minmax' do it 'must have a minimum' do subject.min.must_equal 5 end it 'must minimum with another Point' do subject.min(Point[4,7]).must_equal Point[4,5] subject.min(Point[4,7]).must_be_kind_of Point end it 'must minimum with an Array' do subject.min([4,7]).must_equal Point[4,5] end it 'must minimum with a multiple arguments' do subject.min(4,7).must_equal Point[4,5] end it 'must have a maximum' do subject.max.must_equal 5 end it 'must maximum with another Point' do subject.max(Point[7,2]).must_equal Point[7,5] subject.max(Point[7,2]).must_be_kind_of Point end it 'must maximum with an Array' do subject.max([7,2]).must_equal Point[7,5] end it 'must maximum with multiple arguments' do subject.max(7,2).must_equal Point[7,5] end it 'must have a minmax' do subject.minmax.must_equal [5,5] end it 'must minmax with another Point' do subject.minmax(Point[7,2]).must_equal [Point[5,2], Point[7,5]] end it 'must minmax with an Array' do subject.minmax([7,2]).must_equal [Point[5,2], Point[7,5]] end it 'must maximum with multiple arguments' do subject.minmax(7,2).must_equal [Point[5,2], Point[7,5]] end end describe 'arithmetic' do let(:left) { Point[1,2] } let(:right) { Point[3,4] } it 'must pretend to be a Point' do subject.is_a?(Point).must_equal true subject.kind_of?(Point).must_equal true subject.is_a?(Geometry::PointIso).must_equal true subject.kind_of?(Geometry::PointIso).must_equal true subject.instance_of?(Point).must_equal false subject.instance_of?(Geometry::PointIso).must_equal true end it 'must have +@' do (+subject).must_be :eql?, iso_value (+subject).must_be_instance_of(Geometry::PointIso) end it 'must have unary negation' do (-subject).must_be :eql?, -iso_value (-subject).must_be_instance_of(Geometry::PointIso) end describe 'Accessors' do it 'must return 1 for array access' do subject[3].must_equal iso_value end it 'must return 1 for named element access' do subject.x.must_equal iso_value subject.y.must_equal iso_value subject.z.must_equal iso_value end end it 'must add a number' do (subject + 3).must_equal (iso_value + 3) (3 + subject).must_equal (3 + iso_value) end it 'return a Point when adding two Points' do (subject + right).must_be_kind_of Point (left + subject).must_be_kind_of Point end it 'must return an Array when adding an array' do (subject + [5,6]).must_equal [iso_value+5, iso_value+6] # ([5,6] + subject).must_equal [10, 11] end it 'must return a Point when adding a Size' do (subject + Size[5,6]).must_be_instance_of(Point) (subject + Size[5,6]).must_equal Point[iso_value+5, iso_value+6] end describe 'when subtracting' do it 'must subtract a number' do (subject - 3).must_equal (iso_value - 3) (3 - subject).must_equal(-2) end it 'return a Point when subtracting two Points' do (subject - right).must_equal Point[iso_value - right.x, iso_value - right.y] (left - subject).must_equal Point[left.x - iso_value, left.y - iso_value] end it 'must return a Point when subtracting an array' do (subject - [5,6]).must_equal [0, -1] # ([5,6] - subject).must_equal [4,5] end it 'must return a Point when subtracting a Size' do (subject - Size[5,6]).must_be_instance_of(Point) (subject - Size[5,6]).must_equal Point[0,-1] end end it 'must multiply by a scalar' do (subject * 3).must_equal 15 (subject * 3.0).must_equal 15.0 end it 'must refuse to multiply by a Point' do -> { subject * Point[1, 2] }.must_raise Geometry::OperationNotDefined end it 'must refuse to multiply by a Vector' do -> { subject * Vector[2, 3] }.must_raise Geometry::OperationNotDefined end it 'must divide by a scalar' do (subject / 3).must_equal 5/3 (subject / 4.0).must_equal 5/4.0 end it 'must raise an exception when divided by 0' do -> { subject / 0 }.must_raise ZeroDivisionError end describe 'division' do it 'must raise an exception for Points' do lambda { subject / Point[1,2] }.must_raise Geometry::OperationNotDefined end it 'must raise an exception for Vectors' do lambda { subject / Vector[1,2] }.must_raise Geometry::OperationNotDefined end end end describe 'coercion' do it 'must coerce Arrays into Points' do subject.coerce([3,4]).must_equal [Point[3,4], Point[5, 5]] end it 'must coerce Vectors into Vectors' do subject.coerce(Vector[3,4]).must_equal [Vector[3,4], Vector[5, 5]] end it 'must coerce Points into Points' do subject.coerce(Point[5,6]).must_equal [Point[5,6], Point[5, 5]] end end describe 'comparison' do it 'must be equal to the same value' do subject.must_be :eql?, 5 subject.must_be :eql?, 5.0 end it 'must not be equal to a number of a different value' do 0.wont_equal subject 3.14.wont_equal subject end it 'must be equal to an Array of the same value' do subject.must_be :==, [5,5] subject.must_be :eql?, [5,5] subject.must_be :===, [5,5] [5,5].must_equal subject subject.must_equal [5,5] end it 'must not be equal to an Array of other values' do subject.wont_equal [3, 2, 1] [3, 2, 1].wont_equal subject end it 'must not be equal to a Point at the origin' do subject.wont_be :==, Point[0,0] subject.wont_be :eql?, Point[0,0] subject.wont_be :===, Point[0,0] Point[0,0].wont_equal subject subject.wont_equal Point[0,0] end it 'must not be equal to a Point not at the origin' do subject.wont_equal Point[3,2] Point[3,2].wont_equal subject end it 'must be equal to a Point of subjects' do subject.must_be :==, Point[iso_value, iso_value] subject.must_be :eql?, Point[iso_value, iso_value] subject.must_be :===, Point[iso_value, iso_value] Point[iso_value, iso_value].must_equal subject subject.must_equal Point[iso_value, iso_value] end it 'must be equal to an Vector of the same value' do subject.must_be :eql?, Vector[iso_value, iso_value] Vector[5, 5].must_equal subject end it 'must not be equal to a Vector of other values' do subject.wont_equal Vector[3,2] Vector[3,2].wont_equal subject end end end