require 'rails_helper'

RSpec.describe UnitConversion::ValueUnit do

  def check_vu(vu, value, unit)
    expect(vu.value).to be_a UnitConversion::ParsedNumber
    expect(vu.raw_value).to eq value

    if unit.present?
      expect(vu.unit).to be_a UnitConversion::ParsedUnit
      expect(vu.unit.to_s).to eq unit
    else
      expect(vu.unit).to be_nil
      expect(vu).to be_a UnitConversion::ValueNoUnit
    end
  end

  describe '.for' do

    it 'Converts single strings' do
      check_vu(UnitConversion::ValueUnit.for('5 cups'), 5, 'cup')
      check_vu(UnitConversion::ValueUnit.for('5'), 5, nil)
      check_vu(UnitConversion::ValueUnit.for('1/3 fl oz'), Rational(1,3), 'foz')
    end

    it 'Converts a pair of strings' do
      check_vu(UnitConversion::ValueUnit.for('5', 'cups'), 5, 'cup')
      check_vu(UnitConversion::ValueUnit.for('5', ''), 5, nil)
      check_vu(UnitConversion::ValueUnit.for('1/3', 'fl oz'), Rational(1,3), 'foz')
    end

    it 'Converts a bare Numeric' do
      check_vu(UnitConversion::ValueUnit.for(5, 'cups'), 5, 'cup')
      check_vu(UnitConversion::ValueUnit.for(5, ''), 5, nil)
      check_vu(UnitConversion::ValueUnit.for(Rational(1,3), 'fl oz'), Rational(1,3), 'foz')
      check_vu(UnitConversion::ValueUnit.for(2.5, 'tsp'), 2.5, 'teaspoon')
    end

    it 'Converts ParsedNumber and a string' do
      check_vu(UnitConversion::ValueUnit.for(UnitConversion::ParsedNumber.new('5'), 'cups'), 5, 'cup')
      check_vu(UnitConversion::ValueUnit.for(UnitConversion::ParsedNumber.new('5'), nil), 5, nil)
    end

    it 'Converts parsed objects' do
      check_vu(UnitConversion::ValueUnit.for(UnitConversion::ParsedNumber.new('5'), UnitConversion::ParsedUnit.new('cups')), 5, 'cup')
    end

    it 'converts multi word units' do
      check_vu(UnitConversion::ValueUnit.for('2 cubic inches'), 2, 'inch3')
    end

    it 'understands cubic inches to be volume' do
      expect(UnitConversion::ValueUnit.for('2 cubic inches').volume?).to be_truthy
    end
  end

end