require 'rails_helper' RSpec.describe Recipe, type: :model do describe '.for_criteria' do it 'finds by name' do r1 = create(:recipe, name: 'chicken soup') r2 = create(:recipe, name: 'turkey soup') r3 = create(:recipe, name: 'chicken curry') c = ViewModels::RecipeCriteria.new({page: 1, per: 200}) c.name = 'chicken' r = Recipe.for_criteria(c) expect(r).to contain_exactly(r1, r3) end end describe '.search_by_name' do it 'can be chained' do r1 = create(:recipe, name: 'chicken soup', is_ingredient: true) r2 = create(:recipe, name: 'turkey soup') expect(Recipe.is_ingredient.search_by_name('soup')).to contain_exactly(r1) end end describe '#yields_list' do it 'always has "1 each" as a yield' do r = create(:recipe, yields: '') l = r.yields_list expect(l.length).to eq 1 expect(l.first).to be_a UnitConversion::ValueUnit expect(l.first.value.value).to eq 1 expect(l.first.unit.unit).to eq 'each' end it 'caches the list and resets it when yield is changed' do r = create(:recipe, yields: '3 cups') l1 = r.yields_list l2 = r.yields_list expect(l1.first).to equal(l2.first) r.yields = '4 cups' l2 = r.yields_list expect(l1.first).not_to equal(l2.first) end it 'converts a bare value into a servings unit' do r = create(:recipe, yields: '3') l = r.yields_list expect(l.length).to eq 2 s = l.detect { |y| y.unit.unit == 'servings' } expect(s).to be_a UnitConversion::ValueUnit expect(s.raw_value).to eq 3 expect(s.unit.unit).to eq 'servings' end end describe '#custom_units' do it 'returns nothing if no conversion possible' do r = create(:recipe, yields: '') expect(r.custom_units).to be_empty r = create(:recipe, yields: '3 rolls, 2 buttercups') expect(r.custom_units).to be_empty r = create(:recipe, yields: '1 dealybob') expect(r.custom_units).to be_empty end it 'returns a each mapping for a convertable yields' do r = create(:recipe, yields: '2 1/2 cups') expect(r.custom_units.length).to eq 1 expect(r.custom_units['each']).to be_a UnitConversion::ValueUnit expect(r.custom_units['each'].value.value).to eq 2.5 end it 'creates properly scaled arbitrary units' do r = create(:recipe, yields: '6 Tbsp, 3 glarps') expect(r.custom_units.length).to eq 2 expect(r.custom_units['each']).to be_a UnitConversion::ValueUnit expect(r.custom_units['glarps']).to be_a UnitConversion::ValueUnit expect(r.custom_units['glarps'].value.value).to eq 2 expect(r.custom_units['glarps'].unit.unit).to eq '[tbs_us]' end end describe '#update_rating!' do it 'should set rating to nil with no ratings' do r = create(:recipe) r.update_rating! expect(r.rating).to be_nil create(:log, rating: nil, source_recipe: r) r.update_rating! expect(r.rating).to be_nil end it 'should set rating based on user logs' do user = create(:user) other_user = create(:user) r = create(:recipe, user: user) create(:log, rating: 2, source_recipe: r, user: user) create(:log, rating: 4, source_recipe: r, user: user) create(:log, rating: 5, source_recipe: r, user: other_user) r.update_rating! expect(r.rating).to eq 3 end end describe '#tag_names' do it 'should return tag names' do t1 = create(:tag, name: 'one') t2 = create(:tag, name: 'two') r = create(:recipe) r.tags = [t1, t2] r.save expect(r.tag_names).to contain_exactly('one', 'two') end it 'should set existing tags' do t1 = create(:tag, name: 'one') t2 = create(:tag, name: 'two') r = create(:recipe) r.tag_names = ['one', 'two'] expect(r.tags).to contain_exactly(t1, t2) end it 'should set new tags' do r = create(:recipe) r.tag_names = ['one', 'two'] expect(r.tags.length).to eq 2 expect(r.tags.first.persisted?).to be_truthy end it 'should set new and existing tags' do t1 = create(:tag, name: 'one') t2 = create(:tag, name: 'two') r = create(:recipe) r.tag_names = ['One', 'TWO', 'three'] expect(r.tags).to include(t1, t2) expect(r.tags.length).to eq 3 expect(r.tags.detect {|t| t.is?('THREE')}).not_to be_nil end it 'ignores empty elements' do r = create(:recipe) r.tag_names = ['one', 'two', nil, ''] expect(r.tags.length).to eq 2 end end end