require 'rails_helper' RSpec.describe UnitConversion do describe '.with_custom_units' do it 'can convert' do UnitConversion.with_custom_units({ 'recipe': UnitConversion.parse('4 cups') }) do vu = UnitConversion.parse('2 1/2 recipes') expect(vu.volume?).to be_truthy lu = vu.convert("liters") expect(lu.raw_value).to be_between(2.3, 2.4) expect(lu.unit.to_s).to eq 'liter' end end it 'returns the value of the block' do val = UnitConversion.with_custom_units({ 'recipe': UnitConversion.parse('4 cups') }) do 42 end expect(val).to eq 42 end end describe '.auto_unit' do it 'leaves units alone if reasonable' do expect(UnitConversion.auto_unit('1/2', 'tbsp')).to eq ['1/2', 'tablespoon'] expect(UnitConversion.auto_unit('2', 'cups')).to eq ['2', 'cup'] expect(UnitConversion.auto_unit('1', 'c')).to eq ['1', 'cup'] end it 'leaves units alone if unknown' do expect(UnitConversion.auto_unit('1/16', 'splat')).to eq ['1/16', 'splat'] expect(UnitConversion.auto_unit('4.5', 'dogs')).to eq ['4.5', 'dogs'] expect(UnitConversion.auto_unit('0', '')).to eq ['0', ''] end it 'converts standard volume units correctly' do expect(UnitConversion.auto_unit('6', 'tsp')).to eq ['2', 'tablespoon'] expect(UnitConversion.auto_unit('24', 'tsp')).to eq ['1/2', 'cup'] expect(UnitConversion.auto_unit('1/16', 'cup')).to eq ['1', 'tablespoon'] expect(UnitConversion.auto_unit('1/48', 'cup')).to eq ['1', 'teaspoon'] expect(UnitConversion.auto_unit('768', 'tsp')).to eq ['1', 'gallon'] expect(UnitConversion.auto_unit('6', '[tsp_us]')).to eq ['2', 'tablespoon'] end it 'converts standard mass units correctly' do expect(UnitConversion.auto_unit('32', 'oz')).to eq ['2', 'pound'] expect(UnitConversion.auto_unit('40', 'oz')).to eq ['2 1/2', 'pound'] expect(UnitConversion.auto_unit('3/4', 'lb')).to eq ['12', 'ounce'] expect(UnitConversion.auto_unit('0.0625', 'lb')).to eq ['1', 'ounce'] end end describe '.convert' do it 'scales decimal numbers' do expect(UnitConversion.convert('1', '2', 'cup', 'cup')).to eq '2' expect(UnitConversion.convert('1.5', '2', 'cup', 'cup')).to eq '3' expect(UnitConversion.convert('4', '.5', 'cup', 'cup')).to eq '2' expect(UnitConversion.convert('4', '1/2', 'cup', 'cup')).to eq '2' end it 'scales rational numbers' do expect(UnitConversion.convert('1/2', '2', 'cup', 'cup')).to eq '1' expect(UnitConversion.convert('1 1/2', '2', 'cup', 'cup')).to eq '3' expect(UnitConversion.convert('4', '.5', 'cup', 'cup')).to eq '2' expect(UnitConversion.convert('4', '1/2', 'cup', 'cup')).to eq '2' expect(UnitConversion.convert('2', '1/3', 'cup', 'cup')).to eq '2/3' end it 'converts units' do expect(UnitConversion.convert('1/2', '1', 'cup', 'tbsp')).to eq '8' expect(UnitConversion.convert('8', '1', 'tablespoon', 'cup')).to eq '1/2' expect(UnitConversion.convert('1', '1', 'tablespoon', 'cup')).to eq '1/16' expect(UnitConversion.convert('2.0', '1', 'tablespoon', 'cup')).to eq '0.125' expect(UnitConversion.convert('2/3', '1', 'tablespoon', 'teaspoons')).to eq '2' expect(UnitConversion.convert('2', '4', 'teaspoons', 'tablespoons')).to eq '2 2/3' end it 'scales odd units without conversion' do expect(UnitConversion.convert('1/2', '2', 'slices', 'slices')).to eq '1' expect(UnitConversion.convert('4', '1/8', nil, nil)).to eq '1/2' expect(UnitConversion.convert('4', '1/8', 'slices', nil)).to eq '1/2' expect(UnitConversion.convert('4', '1/8', 'slices', '')).to eq '1/2' end it 'converts and scales' do expect(UnitConversion.convert('1/2', '2', 'cup', 'tbsp')).to eq '16' expect(UnitConversion.convert('2.0', '1 1/2', 'tablespoon', 'cup')).to eq '0.188' expect(UnitConversion.convert('2', '1 1/2', 'tablespoon', 'cup')).to eq '3/16' end it 'converts from volume to mass' do expect(UnitConversion.convert('5', '1', 'cup', 'ounce', '5 oz/c')).to eq '25' end it 'converts from mass to volume' do expect(UnitConversion.convert('25', '1', 'ounce', 'cup', '5 oz/c')).to eq '5' end end describe '.parse' do it 'correctly parses strings to Units' do data = { '4 c' => Unitwise(4, 'cup'), '5.5 oz' => Unitwise(5.5, 'ounce'), '-4 tbsp' => Unitwise(-4, 'tablespoon'), '223 g/c' => Unitwise(223, 'gram/cup'), '1/3 c' => Unitwise("1/3".to_r, 'cup'), '-5/16 g' => Unitwise("-5/16".to_r, 'gram'), '2 1/2 c' => Unitwise("5/2".to_r, 'cup'), '1.03 gram/ml' => Unitwise("1.03", 'g/ml') } data.each do |input, output| expect(UnitConversion.parse(input).unitwise).to eq output end end it 'raises UnknownUnitError with bad units' do data = [ '5 cats', '33 gulps/thinking', '9.2 meeters/s2', '5/8 floor' ] data.each do |input| expect { UnitConversion.parse(input).unitwise }.to raise_error(UnitConversion::UnknownUnitError), "'#{input}' didn't raise" end end it 'raises UnparseableUnitError on malformed string' do data = [ '5.5/2 cups', '2/3.0 cups', 'ounce', '-.4 cups', 'gallons 6', '5,5 tsp' ] data.each do |input| expect { UnitConversion.parse(input) }.to raise_error(UnitConversion::UnparseableUnitError), "'#{input}' didn't raise" end end end end