parsley/spec/models/unit_conversion_spec.rb
2016-01-31 00:00:32 -06:00

254 lines
9.0 KiB
Ruby

require 'rails_helper'
RSpec.describe UnitConversion do
describe '.auto_unit' do
it 'leaves units alone if reasonable' do
expect(UnitConversion.auto_unit('1/2', 'tbsp')).to eq ['1/2', 'tbsp']
expect(UnitConversion.auto_unit('2', 'cups')).to eq ['2', 'cups']
expect(UnitConversion.auto_unit('1', 'c')).to eq ['1', 'c']
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 '.get_value' do
it 'returns rationals' do
expect(UnitConversion.get_value('1/2')).to eq Rational(1, 2)
expect(UnitConversion.get_value('1 1/2')).to eq Rational(3, 2)
expect(UnitConversion.get_value('-1/2')).to eq Rational(-1, 2)
expect(UnitConversion.get_value('-1 1/2')).to eq Rational(-3, 2)
expect(UnitConversion.get_value('18 9/10')).to eq Rational(189, 10)
end
it 'returns decimals' do
expect(UnitConversion.get_value('-1')).to eq -1.to_d
expect(UnitConversion.get_value('1.0')).to eq 1.to_d
expect(UnitConversion.get_value('5.56')).to eq "5.56".to_d
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', nil, 'slices')).to eq '1/2'
expect(UnitConversion.convert('4', '1/8', 'slices', '')).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, 'gram/milliliter')
}
data.each do |input, output|
expect(UnitConversion.parse(input)).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) }.to raise_error(UnitConversion::UnknownUnitError), "'#{input}' didn't raise"
end
end
it 'raises UnparseableUnitError on malformed string' do
data = [
'55',
'55.5',
'-55',
'-55.55',
'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
describe '.density?' do
it 'returns true for any mass over volume unit' do
data = [
Unitwise(1, 'gram/cup'),
Unitwise(1, 'pound/gallon'),
Unitwise(1, 'ounce/tablespoon'),
Unitwise(1, 'ounce/centimeter3')
]
data.each do |input|
expect(UnitConversion.density?(input)).to be_truthy
end
end
it 'returns false for any non density unit' do
data = [
Unitwise(1, 'cup'),
Unitwise(1, 'gram'),
Unitwise(1, 'gram/hour'),
Unitwise(1, 'centimeter3/ounce')
]
data.each do |input|
expect(UnitConversion.density?(input)).to be_falsey
end
end
end
describe '.rationalize' do
it 'leaves integers alone' do
expect(UnitConversion.rationalize(1)).to eq 1
expect(UnitConversion.rationalize(15)).to eq 15
expect(UnitConversion.rationalize(-1)).to eq -1
expect(UnitConversion.rationalize(0)).to eq 0
end
it 'leaves non-fractional numbers alone' do
expect(UnitConversion.rationalize(1.0)).to eq 1.0
expect(UnitConversion.rationalize(-1.0)).to eq -1.0
expect(UnitConversion.rationalize(0.0)).to eq 0.0
expect(UnitConversion.rationalize(35.0)).to eq 35.0
end
it 'leaves already nice rationals alone' do
expect(UnitConversion.rationalize(Rational(1,2))).to eq Rational(1,2)
expect(UnitConversion.rationalize(Rational(5,2))).to eq Rational(5,2)
expect(UnitConversion.rationalize(Rational(3,16))).to eq Rational(3,16)
expect(UnitConversion.rationalize(Rational(3,4))).to eq Rational(3,4)
end
it 'converts neat decimals to rationals' do
expect(UnitConversion.rationalize(1.5)).to eq Rational(3,2)
expect(UnitConversion.rationalize(0.125)).to eq Rational(1,8)
expect(UnitConversion.rationalize(5.0625)).to eq Rational(81, 16)
expect(UnitConversion.rationalize(0.75)).to eq Rational(3,4)
end
it 'rounds weird rationals to nice rationals' do
expect(UnitConversion.rationalize(Rational(3,7))).to eq Rational(7,16)
expect(UnitConversion.rationalize(Rational(2,5))).to eq Rational(3,8)
expect(UnitConversion.rationalize(Rational(2,5))).to eq Rational(3,8)
end
it 'rounds weird decimals to nice rationals' do
expect(UnitConversion.rationalize(0.24)).to eq Rational(1,4)
expect(UnitConversion.rationalize(1.24)).to eq Rational(5,4)
expect(UnitConversion.rationalize(1.13)).to eq Rational(9,8)
end
end
describe '.normalize_unit_name' do
it 'converts simple units' do
data = {
'c' => '[cup_us]',
'cups' => '[cup_us]',
'pints' => '[pt_us]',
'gram' => 'g',
'grams' => 'g',
'Grams' => 'g',
'Tbsp' => '[tbs_us]'
}
data.each do |input, output|
expect(UnitConversion.normalize_unit_names(input)).to eq output
end
end
it 'converts mixed units' do
data = {
'oz/c' => '[oz_av]/[cup_us]',
'kilograms/cups' => 'kg/[cup_us]',
'pints/junk' => '[pt_us]/junk'
}
data.each do |input, output|
expect(UnitConversion.normalize_unit_names(input)).to eq output
end
end
end
end