require 'rails_helper'

RSpec.describe UnitConversion::NumberFormatter do

  describe UnitConversion::RationalFormatter do

    it 'formats integers' do
      expect(UnitConversion::RationalFormatter.new.format(1)).to eq '1'
      expect(UnitConversion::RationalFormatter.new.format(-1)).to eq '-1'
      expect(UnitConversion::RationalFormatter.new.format(1.0)).to eq '1'
    end

    it 'formats rationals into rationals' do
      expect(UnitConversion::RationalFormatter.new.format(Rational(1,2))).to eq '1/2'
      expect(UnitConversion::RationalFormatter.new.format(Rational(5,16))).to eq '5/16'
      expect(UnitConversion::RationalFormatter.new.format(Rational(5, 4))).to eq '1 1/4'
    end

    it 'rounds rationals into better rationals' do
      expect(UnitConversion::RationalFormatter.new.format(Rational(3,7))).to eq '7/16'
    end

    it 'formats decimals into rationals' do
      expect(UnitConversion::RationalFormatter.new.format(1.5)).to eq '1 1/2'
      expect(UnitConversion::RationalFormatter.new.format(1.125)).to eq '1 1/8'
      expect(UnitConversion::RationalFormatter.new.format(24.38)).to eq '24 3/8'
    end
  end

  describe UnitConversion::DecimalFormatter do
    it 'formats everything to a decimal' do
      expect(UnitConversion::DecimalFormatter.new.format(1)).to eq '1'
      expect(UnitConversion::DecimalFormatter.new.format(-1)).to eq '-1'
      expect(UnitConversion::DecimalFormatter.new.format(1.0)).to eq '1'
      expect(UnitConversion::DecimalFormatter.new.format(Rational(1,4))).to eq '0.25'
      expect(UnitConversion::DecimalFormatter.new.format("4.2899999999".to_d)).to eq '4.29'
    end
  end
  
  describe '.rationalize' do
    it 'leaves integers alone' do
      expect(UnitConversion::NumberFormatter.new.rationalize(1)).to eq 1
      expect(UnitConversion::NumberFormatter.new.rationalize(15)).to eq 15
      expect(UnitConversion::NumberFormatter.new.rationalize(-1)).to eq -1
      expect(UnitConversion::NumberFormatter.new.rationalize(0)).to eq 0
    end

    it 'leaves non-fractional numbers alone' do
      expect(UnitConversion::NumberFormatter.new.rationalize(1.0)).to eq 1.0
      expect(UnitConversion::NumberFormatter.new.rationalize(-1.0)).to eq -1.0
      expect(UnitConversion::NumberFormatter.new.rationalize(0.0)).to eq 0.0
      expect(UnitConversion::NumberFormatter.new.rationalize(35.0)).to eq 35.0
    end

    it 'leaves already nice rationals alone' do
      expect(UnitConversion::NumberFormatter.new.rationalize(Rational(1,2))).to eq Rational(1,2)
      expect(UnitConversion::NumberFormatter.new.rationalize(Rational(5,2))).to eq Rational(5,2)
      expect(UnitConversion::NumberFormatter.new.rationalize(Rational(3,16))).to eq Rational(3,16)
      expect(UnitConversion::NumberFormatter.new.rationalize(Rational(3,4))).to eq Rational(3,4)
    end

    it 'converts neat decimals to rationals' do
      expect(UnitConversion::NumberFormatter.new.rationalize(1.5)).to eq Rational(3,2)
      expect(UnitConversion::NumberFormatter.new.rationalize(0.125)).to eq Rational(1,8)
      expect(UnitConversion::NumberFormatter.new.rationalize(5.0625)).to eq Rational(81, 16)
      expect(UnitConversion::NumberFormatter.new.rationalize(0.75)).to eq Rational(3,4)
    end

    it 'rounds weird rationals to nice rationals' do
      expect(UnitConversion::NumberFormatter.new.rationalize(Rational(3,7))).to eq Rational(7,16)
      expect(UnitConversion::NumberFormatter.new.rationalize(Rational(2,5))).to eq Rational(3,8)
      expect(UnitConversion::NumberFormatter.new.rationalize(Rational(2,5))).to eq Rational(3,8)
    end

    it 'rounds weird decimals to nice rationals' do
      expect(UnitConversion::NumberFormatter.new.rationalize(0.24)).to eq Rational(1,4)
      expect(UnitConversion::NumberFormatter.new.rationalize(1.24)).to eq Rational(5,4)
      expect(UnitConversion::NumberFormatter.new.rationalize(1.13)).to eq Rational(9,8)
    end
  end
  
end