require 'spec_helper' describe Yuyi::Menu do before do # reset current menu instance Yuyi::Menu.send :class_variable_set, :'@@menu', nil allow_any_instance_of(Yuyi::Menu).to receive(:load_from_file) allow_any_instance_of(Yuyi::Menu).to receive(:set_sources) allow_any_instance_of(Yuyi::Menu).to receive(:set_rolls) @menu = Yuyi::Menu.new 'spec/fixtures/menu.yaml' end # CLASS METHODS # describe 'class methods' do describe '.add_roll' do before do class MenuAddRollRoll; end Yuyi::Menu.add_roll :menu_add_roll_roll, MenuAddRollRoll end it 'should add a roll instance' do expect(@menu.instance_var(:rolls)[:menu_add_roll_roll]).to be_a MenuAddRollRoll end end end # INSTANCE METHODS # describe 'instance methods' do describe '#load_from_file' do before do # reset yaml var @menu.send :instance_variable_set, :'@yaml', nil allow(@menu).to receive(:load_from_file).and_call_original allow(@menu).to receive(:get_menu_path) end after do allow(@menu).to receive(:get_menu_path).and_call_original end context 'when the path is invalid' do before do @menu.send :load_from_file, 'foo' end it 'should not set the yaml variable' do expect(@menu.instance_var(:yaml)).to be nil end it 'should not set the menu_path variable' do expect(@menu.instance_var(:menu_path)).to be nil end it 'should call #get_menu_path' do expect(@menu).to have_received(:get_menu_path) end end context 'when the path is local' do before do @menu.send :load_from_file, 'spec/fixtures/menu.yaml' end it 'should set the yaml variable' do expect(@menu.instance_var(:yaml)).to be_a Hash end it 'should set the yaml variable' do expect(@menu.instance_var(:menu_path)).to be_a String end end context 'when the path is remote' do before do @tmp_dir = Dir.mktmpdir stub_const 'Yuyi::DEFAULT_MENU', File.join(@tmp_dir, 'yuyi_menu') remote_file = 'file://' << File.join(File.dirname(__FILE__), '../../fixtures/menu.yaml') @menu.send :load_from_file, remote_file end after do FileUtils.rm File.join(@tmp_dir, 'yuyi_menu_remote') end it 'should set the yaml variable' do expect(@menu.instance_var(:yaml)).to be_a Hash end it 'should set the yaml variable' do expect(@menu.instance_var(:menu_path)).to be_a String end it 'should create a _remote local menu file' do expect(File.exist?(File.join(@tmp_dir, 'yuyi_menu_remote'))).to be true end end end describe '#get_menu_path' do before do tmp_dir = Dir.mktmpdir FileUtils.cp File.join(File.dirname(__FILE__), '../../fixtures/menu.yaml'), tmp_dir stub_const 'Yuyi::DEFAULT_MENU', File.join(tmp_dir, 'menu.yaml') @menu.send :instance_variable_set, :'@yaml', nil allow(Readline).to receive(:readline).and_return('foo', 'bar', '') allow(@menu).to receive(:load_from_file).and_call_original end after do allow(Readline).to receive(:readline).and_call_original end it 'should prompt the user to enter a menu path' do expect(@menu).to receive(:load_from_file).exactly(3).times @menu.send :get_menu_path end end describe '#set_sources' do before do allow(Yuyi::Source).to receive(:new) allow(@menu).to receive(:set_sources).and_call_original @menu.send :instance_variable_set, :'@yaml', { :sources => { :foo => 'bar' }} @menu.send :set_sources end after do allow(Yuyi::Source).to receive(:new).and_call_original end it 'should create a source object from the menu' do expect(Yuyi::Source).to have_received(:new).with :foo, 'bar' end end describe '#set_rolls' do before do allow(@menu).to receive(:set_rolls).and_call_original allow(@menu).to receive(:find_roll) @menu.send :instance_variable_set, :'@yaml', { :rolls => { :foo_roll => {}}} @menu.send :set_rolls end after do allow(@menu).to receive(:find_roll).and_call_original end it 'should require rolls' do expect(@menu).to have_received(:find_roll) end end describe '#order' do before do class MenuOrderOne; end class MenuOrderTwo; end allow(MenuOrderOne).to receive :appetizers allow(MenuOrderTwo).to receive :appetizers allow(MenuOrderOne).to receive :entree allow(MenuOrderTwo).to receive :entree allow(MenuOrderOne).to receive :dessert allow(MenuOrderTwo).to receive :dessert allow(@menu).to receive(:sorted_rolls).and_return([:menu_order_one, :menu_order_two]) @menu.instance_var :rolls, { :menu_order_one => MenuOrderOne, :menu_order_two => MenuOrderTwo } @menu.send :order end after do allow(@menu).to receive(:sorted_rolls).and_call_original end it 'should initialize a roll with the roll options' do expect(MenuOrderOne).to have_received(:appetizers).ordered expect(MenuOrderTwo).to have_received(:appetizers).ordered expect(MenuOrderOne).to have_received(:entree).ordered expect(MenuOrderTwo).to have_received(:entree).ordered expect(MenuOrderOne).to have_received(:dessert).ordered expect(MenuOrderTwo).to have_received(:dessert).ordered end end describe '#sorted_rolls' do before do @menu.instance_var :rolls, { :dependency_roll => OpenStruct.new({ :dependencies => ['foo', 'bar'] }), :foo => OpenStruct.new({ :dependencies => [] }), :bar => OpenStruct.new({ :dependencies => [] }) } end it 'should add the roll to the class var' do expect(@menu.send(:sorted_rolls).sort_by { |sym| sym.to_s }).to eq([:bar, :dependency_roll, :foo]) end end describe '#find_roll' do before do allow(@menu).to receive :require_roll end context 'when a source is specified' do before do @menu.send :find_roll, :foo_roll, { :source => 'foo_source' } end it 'should require the specific roll' do expect(@menu).to have_received(:require_roll).once.with(:foo_roll, 'foo_source/foo_roll') end end context 'when no source is specified' do before do class TestSourceA; end class TestSourceB; end allow(TestSourceA).to receive(:rolls).and_return({ :foo_roll => 'foo_roll' }) allow(TestSourceB).to receive(:rolls).and_return({ :bar_roll => 'bar_roll' }) @menu.var :sources, [TestSourceA, TestSourceB] end it 'should require the first roll found' do expect(@menu).to receive(:require_roll).once.with(:bar_roll, 'bar_roll') @menu.send :find_roll, :bar_roll end end context 'when no roll is found' do before do class TestSource; end allow(TestSource).to receive(:rolls).and_return({}) @menu.var :sources, [TestSource] end it 'should not attempt to require a roll' do expect(@menu).to_not receive(:require_roll) @menu.send :find_roll, :no_roll end end end describe '#options' do before do @menu.instance_var :yaml, { :rolls => { :foo_roll => { :foo => :bar } } } end it 'should return roll options' do expect(@menu.options(:foo_roll)[:foo]).to eq :bar end end end end